这里有一些代码:
#include <string>
#include <iostream>
#include <initializer_list>
template <typename T>
class Test
{
public:
Test(std::initializer_list<T> l)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Test(const Test<T>& copy)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Test() = delete;
Test(Test&&) = delete;
};
void f(const Test<Test<std::string>>& x)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void f(const Test<std::string>& x)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
f({x});
}
int main()
{
Test<std::string> t1 {"lol"};
f(t1);
return 0;
}
这里的问题是,我想在这里调用过载void f(const Test<Test<std::string>>& x)
:
f({x});
我知道如果我这样称呼它:
f(Test<Test<std::string>>{x});
它会完成任务的
我只是不太明白第一种情况下的编译情况
我认为f({x})
行应该是
- 创建临时对象
Test<std::string>
- 将const引用参数绑定到该对象
- 递归继续进行并转到步骤1
相反,它只是一遍又一遍地传递相同的初始对象,并且没有创建临时对象。就好像x
和{x}
是一样的。为什么编译器会这样做?
我的操作系统:
Linux Mint 19 Tara
编译器:
gcc 7.3.0
编译命令:
g++-std=c++11-O0测试.cpp-o测试-墙壁-迂腐
我认为行f({x}(应该:
-创建临时对象测试
你错了,
{x}
从x
(身份(构建const Test<std::string>&
。
因为这两个候选人是:
void f(const Test<Test<std::string>>&)
#1void f(const Test<std::string>&)
#2
overload_resolution很复杂,但目前,#2是更好的匹配(精确匹配(。
#1