C++模板化构造函数不会编译

kmh*_*ann 7 c++ templates constructor typedef typename

为什么我不能用上面的构造函数实例化一个Foo类型的对象?

我有一个使用内部typedef的类Bar(作为"template typedefs"的解决方法),并打算在构造函数中使用它,如下所示(CASE 1).但是,我似乎没有得到它编译.这是合法的C++吗?案例2似乎表明问题与Bar中的typedef有关.

如何定义一个构造函数来接受带有Bar类型的对象的std :: vectors?

#include <vector>
#include <iostream>
#include <utility>

template <typename T>
struct Bar
{
    typedef std::pair<T, T> type; // or anything else that uses T
};

struct Foo
{
    Foo() {}

    // CASE 1: doesn't compile
    template <typename T> explicit Foo( const std::vector<typename Bar<T>::type>& data )
    {
        std::cout << "Hello\n";
    }

    //// CASE 2: compiles, but it's not what I want
    //template <typename T> explicit Foo( const std::vector<Bar<T> >& data )
    //{
    //  std::cout << "Hello\n";
    //}
};

int main()
{
    std::vector<Bar<int>::type> v; // for CASE 1
    //std::vector<Bar<int> > v; // for CASE 2

    Foo f( v );
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Luc*_*lle 10

根据C++标准的第14.8.2.1段,当模板参数仅在非推导的上下文中使用时,不能推导出相应的模板参数:

如果模板参数未在函数模板的任何函数参数中使用,或者仅在非推导的上下文中使用,则无法从函数调用推断出其对应的模板参数,并且必须明确模板参数指定.

非限制上下文的定义,如第14.8.2.4节所述:

非受限的上下文是:

  • 使用qualified-id 指定的类型的嵌套名称说明符.

  • 作为模板id的类型,其中一个或多个模板参数是引用模板参数的表达式.

Bar<T>::type,Bar<T>是一个嵌套名称说明符,因此是一个非推导的上下文,所以你必须在调用构造函数时显式指定模板参数...这是不可能的(即你不能写Foo f<int>(v)).

我想编译器不能推导出模板参数,因为这至少是麻烦的,而且可能是不可能的:想象Bar是专门的:

template<typename T>
struct Bar
{
    typedef std::pair<T,T> type;
};

template<>
struct Bar<char>
{
    typedef std::pair<int,int> type;
};
Run Code Online (Sandbox Code Playgroud)

现在,在调用Foo的构造函数时,我有一个歧义std::vector<std::pair<int,int> >:模板参数应该是int还是char?即使没有这种歧义,你也可以很容易地看到编译器在使用正确的typedef找到实例化之前必须实例化任何类型的Bar(好吧,我不太确定上面的语句是真正相关的,因为我经常找出编译器比我想象的要聪明得多:-)!)