[英]function template overload resolution with user defined conversion operator
What is the correct output for following code according to C++11 standard? 根据C ++ 11标准,以下代码的正确输出是什么?
#include <iostream>
template <typename X>
class A
{
public:
A()
{
std::cout << "A::A" << std::endl;
}
A(const A<X>&)
{
std::cout << "A::A(const A<X>&)" << std::endl;
}
A<X>& operator = (const A<X>&)
{
std::cout << "A::opeartor =(conat A&)" << std::endl;
return *this;
}
};
void* GetData()
{
// return data based on some condition
static A<int> a;
return &a;
}
class P
{
public:
template <typename T>
operator T&()
{
void* pData = GetData();
std::cout << "P::operator T&()" << std::endl;
return *(reinterpret_cast<T*>(pData));
}
operator A<int>()
{
std::cout << "P::opeartor A<int>" << std::endl;
return A<int>();
}
};
int main(int /*argc*/, char** /*argv*/)
{
P objP;
A<int> objA = objP; // case 1
objA = objP; // case 2
return 0;
}
clang and gcc produce following output. clang和gcc产生以下输出。
P::opeartor A<int>
A::A
A::A
P::operator T&()
A::opeartor =(conat A&)
VS 2015 generates output as shown below. VS 2015生成输出,如下所示。
A::A
P::operator T&()
A::A(const A<X>&)
P::operator T&()
A::opeartor =(conat A&)
Case 1 情况1
VS2015 picks template version where as gcc and clang picks non template version. VS2015选择模板版本,其中gcc和clang选择非模板版本。
Case 2 案例2
All three compilers pick template version. 所有三个编译器都选择模板版本。
How can we explain this behavior with reference to C++ 11 standard? 我们如何参考C ++ 11标准来解释这种行为?
MSVC is wrong. MSVC错了。 The behavior here depends on whether the destination type is a reference type, which affects the set of candidate functions.
此处的行为取决于目标类型是否为引用类型,这会影响候选函数集。
In copy-initialization of an object ( A<int> objA = objP;
), the applicable rules in [dcl.init]/17 says that the destination type is A<int>
and the candidate set is governed by [over.match.copy] , under whose rules that it includes both conversion functions; 在对象的复制初始化(
A<int> objA = objP;
)中, [dcl.init] / 17中的适用规则表示目标类型为A<int>
,候选集由[over.match]管理.copy] ,其规则包括转换功能; they are tied, and the template/non-template tiebreaker selects the non-template. 它们是绑定的,模板/非模板仲裁器选择非模板。
In initializing a reference const A<int>&
(the parameter of operator=
), [dcl.init.ref]/5 applies, which says that you first do overload resolution with a candidate set specified by [over.match.ref] , which, when initializing an lvalue reference to object, includes only conversion function returning references. 在初始化引用
const A<int>&
( operator=
的参数)时, [dcl.init.ref] / 5适用,这表示您首先使用[over.match.ref]指定的候选集进行重载解析,当初始化对象的左值引用时,仅包括返回引用的转换函数。
Thus in this case the only candidate is the template; 因此,在这种情况下,唯一的候选人是模板; it proves viable and is selected.
它证明是可行的并且被选中。 The non-template isn't even considered.
甚至没有考虑非模板。
This also means that A<int> objA(objP);
这也意味着
A<int> objA(objP);
will use the template, because there you do overload resolution on the constructors of A<int>
, and will be trying to initialize the const A<int>&
parameter of A<int>
's copy constructor. 将使用该模板,因为您在
A<int>
的构造函数上执行重载解析,并将尝试初始化A<int>
的复制构造函数的const A<int>&
参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.