如何以及何时使用构造函数模板?

时间:2013-06-04 15:41:35

标签: c++

我对下面的句子感到困惑,我理解他们用于转换成员函数的例子但不了解构造函数成员函数模板的场合,helpful example given by Mankarse

  

因为显式模板参数列表遵循函数模板名称,   并且因为调用了转换成员函数模板和构造函数成员函数模板   如果不使用函数名,就无法为这些函数提供显式模板参数列表   功能模板。 --14.5.2.5 N3242

struct A {
    template <class T> operator T*();
};
template <class T> A::operator T*(){ return 0; }
template <> A::operator char*(){ return 0; } // specialization
template A::operator void*(); // explicit instantiation

int main() 
{
   A a;
   int *ip;
   ip = a.operator int*(); // explicit call to template operator
   // A::operator int*()
}

  

类模板的成员函数的模板参数由template-arguments确定   调用成员函数的对象类型--14.5.1.1.2 N3242

所以我需要自己扣除模板参数或使用包装器。
libstdc ++在读取标准库时给出的示例:

template<typename _Container>
class back_insert_iterator
: public iterator<output_iterator_tag, void, void, void, void>
{
   protected:
      _Container* container;
   public:
       explicit
       back_insert_iterator(_Container& __x) : container(&__x) { }
}
/*
 *it use a wrapper :
 */
template<typename _Container>
inline back_insert_iterator<_Container>
back_inserter(_Container& __x)
{ return back_insert_iterator<_Container>(__x); }

2 个答案:

答案 0 :(得分:5)

您永远不能为构造函数模板提供显式模板参数列表。构造函数模板必须始终推导出它们的参数:

struct A {
    template<typename U> A() {}
};
template <typename T>
struct B {
    B() {}
};
struct C {
    template<typename U> C(U t) {}
};
template <typename T>
struct D {
    template<typename U> D(U t) {}
};

int main()
{
    //auto a1 = A<int>{}; //illegal -- A is not a template
    //A can never be instantiated...

    auto b = B<int>{}; //default-constructs a B<int>

    //auto c = C<double>{1.}; //illegal - C not a template

    //Constructs a C, deduces `U = double` constructor:
    auto c = C{1.};
    //Constructs a D<int>, deduces `U = double` constructor:
    auto d = D<int>{1.};
}

答案 1 :(得分:1)

您可以使用中间模板类为ctor制作显式参数 - 它会推导出您想要的类型

#include <iostream>
using namespace std;

template <typename T> struct tag { using type = T;};

class My {
public:
    template <typename T> My(tag<T>) {
        cout << "ctor of " << typeid(T).name();
    }
};

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

    auto a = My(tag<int>());
}