Kyl*_*yle 6 c++ gcc templates constructor friend
为什么
class A;
template<typename T> class B
{
private:
A* a;
public:
B();
};
class A : public B<int>
{
private:
friend B<int>::B<int>();
int x;
};
template<typename T>
B<T>::B()
{
a = new A;
a->x = 5;
}
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
造成
../src/main.cpp:15:错误:无效使用构造函数作为模板
../src/main.cpp:15:注意:使用'B :: B'而不是'B :: class B'来在限定名称中命名构造函数
尚未改变friend B<int>::B<int>()到friend B<int>::B()结果
../src/main.cpp:15:错误:没有在类'B'中声明的'void B :: B()'成员函数
完全删除模板
class A;
class B
{
private:
A* a;
public:
B();
};
class A : public B
{
private:
friend B::B();
int x;
};
B::B()
{
a = new A;
a->x = 5;
}
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
编译并执行得很好 - 尽管我的IDE说朋友B :: B()是无效的语法?
根据CWG缺陷147的分辨率(分辨率已合并到C++ 03中),命名类模板特化的非模板构造函数的正确方法是:
B<int>::B();
Run Code Online (Sandbox Code Playgroud)
并不是
B<int>::B<int>();
Run Code Online (Sandbox Code Playgroud)
如果允许后者,那么当你有一个类模板特化的构造函数模板特化时会有一个歧义:第二个<int>是类模板还是构造函数模板?(有关详细信息,请参阅上面链接的缺陷报告)
因此,将类模板特化的构造函数声明为朋友的正确方法是:
friend B<int>::B();
Run Code Online (Sandbox Code Playgroud)
Comeau 4.3.10.1和Intel C++ 11.1都接受这种形式.Visual C++ 2008和Visual C++ 2010都不接受该表单,但都接受(不正确)表单friend B<int>::B<int>();(我将在Microsoft Connect上提交缺陷报告).
gcc不接受4.5版之前的任何一种形式. 针对gcc 3.0.2报告了错误5023,但错误报告中请求的解决方案是无效表单.看来bug 9050的解决方案也解决了这个问题,gcc 4.5接受了正确的表格.Georg Fritzsche在对该问题的评论中对此进行了验证.
| 归档时间: |
|
| 查看次数: |
1432 次 |
| 最近记录: |