关于模板类中模板函数的小问题 我试图理解一些C++语法: template<class T> class Foo { Foo(); template<class U> Foo(const Foo<U>& other); }; template<class T> Foo<T>::Foo() { /*normal init*/ } template<class T> template<class U> Foo<T>::Foo(const Foo<U>& other) { /*odd copy constructed Foo*/ }
所以,我写了这样的代码,在windows和linux中编译得很好。我不明白的是为什么复制构造函数有两个这样定义的模板。基本上,在找到正确的语法之前,我必须先过一段时间,我想知道为什么特定的语法是正确的,而不是类似于模板的东西。第一个带参数T的模板说,类是用参数T模板化的 参数为U的第二个模板表示参数为T的模板类的成员函数是参数为U的模板-即构造函数 实际上,这里有一个模板类,它将生成和用作构造函数参数的类型一样多的复制构造函数 在复制构造函数的特定情况下,您不应该这样做,而是应该:关于模板类中模板函数的小问题 我试图理解一些C++语法: template<class T> class Foo { Foo(); template<class U> Foo(const Foo<U>& other); }; template<class T> Foo<T>::Foo() { /*normal init*/ } template<class T> template<class U> Foo<T>::Foo(const Foo<U>& other) { /*odd copy constructed Foo*/ },c++,templates,C++,Templates,所以,我写了这样的代码,在windows和linux中编译得很好。我不明白的是为什么复制构造函数有两个这样定义的模板。基本上,在找到正确的语法之前,我必须先过一段时间,我想知道为什么特定的语法是正确的,而不是类似于模板的东西。第一个带参数T的模板说,类是用参数T模板化的 参数为U的第二个模板表示参数为T的模板类的成员函数是参数为U的模板-即构造函数 实际上,这里有一个模板类,它将生成和用作构造函数参数的类型一样多的复制构造函数 在复制构造函数的特定情况下,您不应该这样做,而是应该: templa
template<class T>
class Foo
{
Foo();
Foo(const Foo<T>& other);
};
template<class T>
Foo<T>::Foo() { /*normal init*/ }
template<class T>
Foo<T>::Foo(const Foo<T>& other) { /*odd copy constructed Foo*/ }
因为在您的示例中,不是复制构造函数,而是将类型U作为参数的构造函数:转换构造函数。。。这很难预测。第一个带参数T的模板表示该类是用参数T模板化的 参数为U的第二个模板表示参数为T的模板类的成员函数是参数为U的模板-即构造函数 实际上,这里有一个模板类,它将生成和用作构造函数参数的类型一样多的复制构造函数 在复制构造函数的特定情况下,您不应该这样做,而是应该:
template<class T>
class Foo
{
Foo();
Foo(const Foo<T>& other);
};
template<class T>
Foo<T>::Foo() { /*normal init*/ }
template<class T>
Foo<T>::Foo(const Foo<T>& other) { /*odd copy constructed Foo*/ }
因为在您的示例中,不是复制构造函数,而是将类型U作为参数的构造函数:转换构造函数。。。这很难预测。对于涉及的每个模板,都必须有单独的模板子句。这里涉及两个模板,它们都应该具有非空模板子句:
类模板Foo
构造函数模板
考虑这种情况,由于参数U所属位置的模糊性而失败
template<typename T>
struct A {
template<typename U> void f();
};
template<typename T, typename U>
void A<T>::f() { }
当我们有单独的模板子句来捕获各自的参数时,这就更自然了。因此,上述错误定义的语法是
template<typename T>
template<typename U>
void A<T>::f() { }
现在,代码的读者也会立即看到这是一个成员模板的定义,而不是一个可能意外声明但未使用的第二个参数。对于涉及的每个模板,它必须有单独的模板子句。这里涉及两个模板,它们都应该具有非空模板子句:
类模板Foo
构造函数模板
考虑这种情况,由于参数U所属位置的模糊性而失败
template<typename T>
struct A {
template<typename U> void f();
};
template<typename T, typename U>
void A<T>::f() { }
当我们有单独的模板子句来捕获各自的参数时,这就更自然了。因此,上述错误定义的语法是
template<typename T>
template<typename U>
void A<T>::f() { }
现在,代码的读者也立即看到,这是一个成员模板的定义,而不是一个潜在的意外声明但未使用的第二个参数。希望从一个Foo隐式构造一个Foo是有正当理由的,但你是对的,它不是一个真正的复制构造函数。实际上,在我的实际代码中,我有Foo和Foo类型的构造函数,但这一点很好。我很高兴编译器能解决这个问题。是的,这是必要的,因为正如T.麦克亨利所说,在某些情况下,你需要这种行为。例如,当您想要管理多种类型的数字类型时,最好将您的成员函数模板化为所有类型只有一个定义,忽略它是一个类还是一个基本类型。想象一下shared_ptr,它允许从shared_ptr构造,只要U*转换为T*我建议编辑:…复制构造函数的数量与类型的数量相同。。。并从此行中删除副本。正如你在后面指出的,这从来不是一个复制构造函数-即使他留下了这个构造函数,他也应该添加你的版本。想要从一个Foo隐式构造一个Foo可能有正当的理由,但你是对的,那它不是一个真正的复制构造函数。实际上,在我的实际代码中,我有Foo和Foo类型的构造函数,但这一点很好理解。我很高兴编译器能解决这个问题。是的,这是必要的,因为正如T.麦克亨利所说,在某些情况下,你需要这种行为。例如,当您想要管理多种类型的数字类型时,最好将您的成员函数模板化为所有类型只有一个定义,忽略它是一个类还是一个基本类型。想象一下shared_ptr,它允许从shared_ptr构造,只要U*转换为T*我建议编辑:…复制构造函数的数量与类型的数量相同。。。并从此行中删除副本。正如你在后面指出的,这永远不是一个复制构造函数——即使他留下了这个构造函数,他也应该添加你的版本。这不是一个复制构造函数。如果你试图使用pa,编译器会抱怨 ss类Foo的值。这不是一个复制构造函数。如果您试图按值传递类Foo,编译器将发出抱怨。