简体   繁体   English

函数模板重载决策与用户定义的转换运算符

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM