4

저는 프로젝트에서 템플릿 변형 명시 연산자를 사용하여 변형 된 유사 유형의 명시적인 변환을 구현했습니다. 내 문제를 재현 최소한의 예는 다음 (14 ++ C 모드)과 같은 : 내가 직면명시 적 변환 연산자 템플릿의 우선 순위와 모호성

#include <iostream> 
#include <stdexcept> 
#include <cmath> 

using namespace std; 

class A 
{ 
     public: 
     template<typename T> explicit operator T() const // 1 
     { 
       cout << "operator T" << endl; 
       return T(); 
     } 

     template<typename T> explicit operator const T&() const // 2 
     { 
       cout << "operator const T&" << endl; 
       throw runtime_error("operator const T&"); 
     } 

     template<typename T> explicit operator T&() // 3 
     { 
       cout << "operator T&" << endl; 
       throw runtime_error("operator T&"); 
     } 


}; 


int main(int, char**) 
{ 
     try 
     { 
       const A& a = A(); 
       cout << abs(static_cast<double>(a) - 3.14) << endl; 
     } 
     catch (const runtime_error&) 
     { 

     } 

     return 0; 
} 

문제는 static_cast 변환을 위해 선택한 연산자입니다. GCC의 경우 예상되는 (1) 경우입니다. 출력은 다음과 같습니다

operator T 
3.14 

그러나 연타는 다음과 같은 출력이 컴파일을 거부 :

main.cpp:37:20: error: ambiguous conversion for static_cast from 'const A' to 'double' 
      cout << std::abs(static_cast<double>(a) - 3.14) << endl; 
          ^~~~~~~~~~~~~~~~~~~~~~ 
main.cpp:10:32: note: candidate function [with T = double] 
    template<typename T> explicit operator T() const 
           ^
main.cpp:16:32: note: candidate function [with T = double] 
    template<typename T> explicit operator const T&() const 
           ^
1 error generated. 

연타가 변환이 생각하는 이유 (2), 그것은 분명히 변환 순서에 추가 생성자 호출을 필요로 할 때, 동안 (1) 않을까요? 그리고 그것이 옳은가? (그리고 GCC는 틀린가?) 그렇게하고 있는가?

+0

하지만 왜이 작업을 수행할까요? ''연산자 T()''와''연산자 const T &''둘 다 갖는 점은 무엇입니까? –

+1

@ArneVogel 실제 코드에서이 코드의 의도는 대체 변환 시퀀스를 제공하는 것입니다. 예를 들어, 변형이 'long double'을 보유하면 '연산자 T()'는 'int'로 변환하는 데 도움이됩니다. 하지만 실제로'static_cast'가 실제로 수행하는 것들을 오해했기 때문에이 값으로의 변환은 실제로 중복됩니다. – aclex

답변

0

static_cast은 암시 적 변환 또는 직접 초기화를 수행합니다. 귀하의 경우에는 암시 적 변환을 수행 할 수 없지만 직접 초기 설정 입니다. 왜냐하면 static_castexplicit constructors and conversion functions을 고려하기 때문입니다. 내 생각에 두 가지 가능한 직접적인 intialisations 및 그에 따라 불평을 식별 clang (제 생각에는 정확하게)입니다. GCC 내부에서 무슨 일이 벌어지고 있는지 확신 할 수 없지만 다른 것들이 존재하는지 여부에 관계없이 찾을 수 있다면 기본값은 operator T() 일 것입니다.

+0

예, 동의하는 경향이 있습니다. 분명히'static_cast'는'new-type'을 직접 초기화하지 않고 명시 적으로 사용자 정의 된 변환을 수행하지 않습니다. 그리고이 초기화를 위해서'operator T'와'operator const T '가 적합 해 보입니다. 이 점에 대해 지적 해 주셔서 감사합니다. 적합한 사용자 정의 변환이 선택되는 방식은 아직 명확하지 않습니다. 변환 절차가 암시 적 변환과 같지만 정의 된 명시 적 변환을 고려할 때 해상도가 복사 생성의 가능성을 기반으로하는 것보다 그렇습니다. 그렇기 때문에 두 연산자가 동등하게 적합합니다. – aclex