2016-11-16 16 views
1

생성자 템플릿을 조건부로 활성화하려고합니다. 완전히 C++ 11 호환 컴파일러를 사용하면 여분의 기본 템플릿 인수를 사용하여이를 수행하는 방법을 알고 있습니다. 그러나, 나는 std :: enable_if하지만 기본 함수 템플릿 인수를 지원하지 않는 VS2012를 지원해야합니다. C++ 11enable_if 및 VS2012 생성자

, 나는 다음과 같은 작성합니다

template<typename T> 
struct Class 
{ 
    template<typename O, 
      typename = typename std::enable_if<std::is_convertible<O*, T*>::value>::type> 
    Class(O*) {} 
}; 

을 나는 다음과 같은 노력하지만 오류 C4336 다양한 후속 오류 제공 :

template<typename T> 
struct Class 
{ 
    template <typename O> 
    Class(O*, typename std::enable_if<std::is_convertible<O*, T*>::value>::type *= nullptr) 
    { 
    } 
}; 

이 거기를 어떤 방법 으로이 작품 VS2012 만들 수 있습니까?

추가 :

다음과 같이 클래스의 사용법은 다음과 같습니다

struct X { }; 
struct X2 : X { }; 
struct Y { }; 

struct Client 
{ 
    Client(Class<X> x) {} 
    Client(Class<Y> y) {} 
}; 

void test() { 
    X2* x2; 
    Client client(x2); // error C2668: ambiguous call to overloaded function 
        // (without std::enable_if) 
} 
+0

클래스에 다른 생성자가 있습니까? 아니면이 클래스가 유일한 것입니까? – skypjack

+0

실제 클래스에는 다른 생성자도 있습니다. – user2019765

답변

0

귀하는 이므로에 가깝습니다.

template<typename T> 
struct Class 
{ 
    template <typename O> 
    Class(O*, typename std::enable_if<std::is_convertible<O*, T*>::value>::type * = nullptr) 
    { 
    } 
}; 

차이점을 발견 했습니까? *=은 매개 변수 목록 내에서 multiplication/assignment operator으로 구문 분석되었으며 포인터 형식이 아닌 기본 인수가 뒤에 있습니다. 따라서 구문 오류.

토큰을 구성 할 때 가능한 한 많은 문자를 소비하도록 C++ 파서가 지정 되었기 때문입니다 (최대 뭉치 규칙). 공백을 추가하면 두 개의 개별 토큰으로 분리됩니다.

+0

아아 ... 당신이 말했듯이, 그것은 정말 가깝고, 회고 적으로 어리석은 실수였습니다. – user2019765

0

내가, 당신이 도우미 구조 기능을 사용해야 할 것 (I가를 두려워 찾을 수 없습니다입니다 길 주위에). 그러나이 같은 작업을해야합니다 :

template<typename T> 
class Class { 
    template<typename O> 
    Class(O *o, std::true_type) {} 

    template<typename O> 
    Class(O *o, std::false_type) {} 

public: 
    template<typename O> 
    Class(O *o): Class(o, typename std::is_convertible<O*, T*>::type) {} 
}; 

기본적인 아이디어는 어쩌면 및 파견 태그의 하나입니다

#include <type_traits> 

template<typename T> 
struct Class 
{ 
    template<typename O> 
    Class(O* o) { construct(o, std::integral_constant<bool, std::is_convertible<T*, O*>::value>()); } 

    template<class O> 
    void construct(O*, std::true_type) { /* convertible */ } 
    template<class O> 
    void construct(O*, ...) { /* not convertible */ } 
}; 

struct X { }; 
struct Y : public X { }; 

void check() { 
    X x; 
    int i; 
    Class<Y> cl(&x); 
    Class<Y> cl1(&i); 
} 
+0

이것은 흥미로운 아이디어입니다. 그러나 원래 문제는 클래스가 스마트 포인터 템플릿이며,이 솔루션으로 해결되지 않는 다른 클래스의 두 생성자를 호출 할 때 모호한 변환이 있다는 것입니다. 어쩌면 나는 그 상황의 최소 버전을 제공 할 수있다. – user2019765

0

C++ (11) 때문에, 당신은 또한 그렇게 생성자를 위임 사용할 수 있습니다 VS2012에서도 잘 작동합니다.
자세한 내용은 here을 참조하십시오.

+0

의견을 보내 주셔서 감사합니다. 유감스럽게도 위임자 생성자는 VS2012에서 지원되지 않습니다. – user2019765