Как неявно приводить аргументы шаблонного конструктора?

Я перегружаю конструктор шаблонного класса A с разными типами ввода для аргументов скалярного и контейнерного типа:

template<typename T>
class A {
public:
    A();
    A(T&& _val) { printf("non-template constructor\n");} ;
    template<typename iT> A(const iT& _cont) { printf("template constructor\n");};

};


int main(int argc, char const *argv[]) {


    A<float> foo1(0.9);                     //template constructor
    A<float> foo2((float)0.9);              //no-template constructor 
    A<float> foo3(std::vector<int>(5,8));   //template constructor


    return 0;
}

Тем не менее, есть ли способ вызвать принудительно не шаблонный конструктор для неявно приводимых типов, например, передавая double конструктор A<float>()?

1 ответ

Решение

Да, вы можете добавить SFINAE-ограничение в шаблон конструктора:

template<typename iT,
         std::enable_if_t<!std::is_convertible_v<iT&&, T>>* = nullptr>
A(const iT&) { printf("template constructor\n"); }

Это приводит к сбою замены для выведенного типа iT когда iT&& конвертируется в T, который удаляет шаблон конструктора из набора перегрузки.

(Вам нужно #include <type_traits> для различных библиотечных средств, используемых для выражения ограничения.)

Другие вопросы по тегам