Эффективный C++: пункт 41 - путаница с неявными интерфейсами

Я читаю Effective C++, пункт 41 с заголовком "Понимание неявных интерфейсов и полиморфизм во время компиляции". Он дает объяснение этому примеру и следующему, но я не понимаю эту часть.

template<typename T>
void doProcessing(T& w)
{
     if (w.size() > 10 && w != someNastyWidget) {
     ...

..., T должен поддерживать функцию-член размера, ....., но эта функция-член не должна возвращать целочисленный тип. Не нужно даже возвращать числовой тип. В этом отношении ему даже не нужно возвращать тип, для которого оператор > определено! Все, что нужно сделать, это вернуть объект некоторого типа x, такой, что есть оператор > который может быть вызван с и объектом типа x и int...

Не могли бы вы объяснить, о чем идет речь, и привести больше примеров?

1 ответ

Решение

Это означает, что T::size() функция может вернуть все, что можно сравнить (используя >) для int значение.


Давайте посмотрим на три примера:

  1. Вернуть int:

    struct MyT
    {
        // Some stuff...
    
        int size()
        {
            return some_calculation_returning_int();
        }
    
        // Some more stuff...
    };
    
  2. Вернуть объект, который можно преобразовать в int:

    struct MySizeType
    {
        // Some stuff...
    
        operator int()
        {
            return some_calculation_returning_int();
        }
    
        // Some more stuff...
    };
    
    struct MyT
    {
        // Some stuff...
    
        MySizeType size()
        {
            return MySizeType();
        }
    
        // Some more stuff...
    };
    
  3. Вернуть объект, который можно сравнить с > для int:

    struct MyOtherSizeType
    {
        // Some stuff...
    
        operator>(int other)
        {
            return some_calculation_returning_int() > other;
        }
    
        // Some more stuff...
    };
    
    struct MyT
    {
        // Some stuff...
    
        MyOtherSizeType size()
        {
            return MyOtherSizeType();
        }
    
        // Some more stuff...
    };
    

Хотя должно быть совершенно ясно, что можно использовать первый вариант, можно использовать и два других. Это потому, что они, так или иначе, возвращают что-то, что можно сравнить с int значение.

Если мы "расширим" три варианта:

  1. w.size() > 10 просто так, как есть.

  2. w.size() > 10 будет w.size().operator int() > 10, Здесь MySizeType::operator int() функция преобразования будет использоваться для преобразования MySizeType возражать против int значение, которое можно сравнить.

  3. w.size() > 10 будет w.size().operator>(10), Здесь MyOtherType::operator>() Функция будет использоваться для самого сравнения.

Ссылка

  1. перегрузка оператора
  2. определяемое пользователем преобразование
Другие вопросы по тегам