Когда аргументы шаблона требуются в C ++? - PullRequest
3 голосов
/ 08 апреля 2020

Мне любопытно, когда в C ++ требуются аргументы шаблона.

Например, давайте определим класс как

template<typename T> class Add {
    T value;
public:
    Add(T value) : value(value){};

    T operator() (T valrhs){
        return value + valrhs; 
    }
};

Если мы хотим создать объект типа Add, используя double, нам нужно определить его следующим образом, чтобы не получать ошибки,

Add<double> add5 = Add<double>(5.0);

Теперь рассмотрим функцию, определенную следующим образом:

template<typename T, typename Function> T doOperation (T data, Function f){
    return f(data);
}

В коде, если нужно сделать вызов doOperation, аргументы шаблона не потребуются. Например,

std::cout << doOperation(5.0, add5);

выведет 10. Почему doOperation не требует аргументов шаблона, а определение add5 требует аргументов шаблона?

Кроме того, есть ли способ определить это с помощью указателей на функции. Я застрял, пытаясь выяснить, как передать такой функтор, используя указатель функции в качестве переменной параметра, а не второй аргумент шаблона.

Спасибо, любая помощь приветствуется.

Ответы [ 3 ]

12 голосов
/ 08 апреля 2020

В этом коде

std::cout << doOperation(5.0, add5);

Компилятор вычитает аргумент шаблона функции .

В этой строке

Add<double> add5 = Add<double>(5.0);

вам нужно чтобы предоставить аргументы шаблона, поскольку компилятор не будет делать вывод аргумента шаблона класса.

Однако, начиная с c ++ 17, компилятор будет делать вывод аргумента шаблона класса , а затем это прекрасно компилируется

Add add5(5.0);

Вы также можете явно указать руководство по выводам, поскольку в некоторых случаях это может понадобиться

template<typename T>  Add(T) -> Add<T>;

В качестве примечания, ваш класс Add похоже, что его можно заменить функциональным шаблоном, который возвращает лямбду.

template<typename T>
auto Add (T value) { 
    return [value] (T valrhs) { 
        return value + valrhs; 
    }; 
}

Использование будет выглядеть как

auto add5 = Add(5.0);
std::cout << doOperation(5.0, add5);
4 голосов
/ 08 апреля 2020

Когда аргументы шаблона требуются в C ++?

Аргументы шаблона должны предоставляться явно, если они не могут быть выведены - если параметр не имеет аргумента по умолчанию.

Шаблон Аргумент шаблона функции может быть выведен из не шаблонных аргументов. Аргумент шаблона шаблона класса может быть выведен из аргументов конструктора, если класс шаблона имеет руководство по выводу (которое может быть сгенерировано неявно).

Почему doOperation не требует аргументов шаблона

Поскольку аргумент шаблона выводится из аргумента не-шаблона для data.

, но для определения add5 требуются аргументы шаблона?

На самом деле, add5 не требует явных аргументов шаблона. Следующее будет работать:

Add add5(5.0);

... если только вы не используете старую версию C ++, в которой не было шаблонных руководств по вычету (которые были введены в C ++ 17).

1 голос
/ 08 апреля 2020

Начиная с C ++ 17, как было упомянуто выше, существует вывод аргумента класса-шаблона. Но вы должны быть уверены в этом, потому что это может привести к нежелательному результату.

Add a(5.0); // the type Add<double> is deduced

Add b(5); // the type Add<int> is deduced, which may be unwanted, if you need Add<double> 
          // if so you must specify the desired type
...