P. *_*tos 1 c++ templates constructor
最近,当我的类具有只接受一个参数的模板构造函数时,我遇到了一种奇怪的行为.在某些情况下,该课程根本无法初始化.
#include <iostream>
struct Foo
{
template<typename T>
Foo(const T& x)
{
std::cout << "--" << x << std::endl;
}
};
int main(int, char**)
{
Foo f(std::string());
std::cout << "++" << f << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我所拥有的是一个带有你看到的构造函数的Foo结构.在main中,我创建了一个带有空std :: string的新Foo实例.示例编译并输出为:
++1
Run Code Online (Sandbox Code Playgroud)
跆拳道??? 您可能已经注意到这有三个问题.首先,构造函数从未被调用,其次f被打印为"1",第三,没有重载的运算符<<使用cout打印Foo,尽管编译器从不抱怨.这意味着f不是一种Foo.
我略微改变了这个例子:
int main(int, char**)
{
Foo f(std::string(""));
std::cout << "++" << f << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
...并且编译器抛出一个错误,即没有重载的运算符<<并且这是正常的.
int main(int, char**)
{
Foo f(std::string("Hello"));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在的输出是:
--Hello
Run Code Online (Sandbox Code Playgroud)
那是正常的.
问题是当向Foo :: Foo传递一个空对象时,无论是std :: string()还是float()或any_type().我在GCC 4.4和4.6中测试了这个例子,我发现这种行为非常意外.
你有什么意见?这是一个GCC错误还是我错过了什么?
Foo f(std::string());
Run Code Online (Sandbox Code Playgroud)
它似乎没有Foo像你想象的那样创建一个类型的实例.
相反,它声明了一个name函数f,其返回类型是Foo,而参数type是一个函数类型(它不带参数并返回std::string).
它与:
Foo f(std::string (*)()); //same as yours
Run Code Online (Sandbox Code Playgroud)
这和你的函数声明的唯一区别在于,在你的情况下,参数类型是函数类型(最终它最终会衰减到函数指针类型),在我的例子中,参数类型是函数指针类型(不需要衰减)进入指针类型).
至于它为什么打印++1是因为它调用operator<<哪个void* 作为参数,这个函数打印函数的地址.
现在,如果你想声明一个对象,那么你需要使用额外的parens:
Foo f((std::string())); //notice the extra parens!
Run Code Online (Sandbox Code Playgroud)
这声明了一个对象,并调用构造函数:http://ideone.com/Px815
另见本主题: