C++模板typedef作为模板函数参数

4

为什么编译器找不到与read1匹配的内容?我没有看出read1read2之间的区别;像Foo类中的嵌套typedef模板一样,是否存在限制?

template<typename T>
class Handle{};

class Foo{
public:
    typedef Handle<Foo> Handle;
};


template<typename T>
void read1(typename T::Handle){}

template<typename T>
void read2(Handle<T>){}


int main(int argc, char** argv)
{
    Foo::Handle f1;    
    read1(f1);

    Foo::Handle f2;
    read2(f2);
}

G++编译器输出(G++ 4.4.5)

g++ -c -I.  main1.cpp 
main1.cpp: In function ‘int main(int, char**)’:
main1.cpp:37: error: no matching function for call to ‘read1(Handle<Foo>&)’

我删除了冗余的“Internal”命名空间,使示例更加简洁。 - Xeo
使用G++ 4.4.5,您的编辑使代码出错,g++ -c main.cpp main.cpp:8: 错误:声明 ‘typedef class Handle<Foo> Foo::Handle’ main.cpp:3: 错误:改变了‘Handle’的含义,从‘class Handle<Foo>’变为其他含义 main.cpp: 在函数‘int main(int, char**)’中: main.cpp:27: 错误:没有找到与‘read1(Handle<Foo>&)’匹配的函数 - José
2个回答

4
Foo::Handle f1;    
read1(f1);

传递给read1的类型是Handle<Foo>,而不是Foo。

模板不是继承。 Handle<Foo>是一个独立的类,不是Foo,因此没有Handle<Foo>::Handle


3
template<typename T>
void read1(typename T::Handle)
{
}

首先,如果没有提供显式模板参数,例如read1<Foo>(f1),您将无法调用此函数。请了解SFINAE
其次,编译器如何才能找出T是什么?它必须测试您可能编写的所有可能类的所有嵌套typedef。听起来不可能吗?确实是这样。

2
它不必测试您可能编写的每个类;它只需要测试在read1调用点定义的那些类。这是可能的(甚至相对于编译器处理模板所需的某些内容而言很容易),但不符合标准。 - Chris Dodd
为什么可以像read2一样找到参数?它只需要测试Foo,没有其他类型。 - José
它不仅需要测试在该点定义的所有类,还需要测试所有可能的模板实例化(虽然可能以模板形式)。但是它如何解决歧义?通常程序员必须修复这些问题,但在这种情况下,一些完全不相关的代码更改(不同的命名空间等)可能会导致歧义,因此让程序员修复这些问题并不是一个真正的选择。@José:在这个简单的例子中,它可能只需要测试foo,但大多数场景都更加复杂,并且那些不起作用的语言特性并不是很受欢迎。 - Grizzly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接