2016-06-14 4 views
2

친구를 사용하여 템플릿 구조체 내에 함수를 오버로드하려고합니다. 형식을 다른 형식으로 매핑하는 데 사용하고 싶습니다. 아래 코드에서 intMyType으로 매핑하고 싶습니다. 여기 템플릿 친구 함수 : 잘못된 함수가 호출되었습니다.

내가 지금까지 무슨 짓을했는지 :

template<typename T> 
void map(){} // Worst case 

// Here's the class that will overload our function 
template<typename Type, typename T> 
struct MakeFunction { 
    // Compilation error. 
    friend Type map<T>() { return {}; } 
}; 

struct MyType : MakeFunction<MyType, int> {}; 

int main() { 
    std::cout << typeid(decltype(map<int>())).name() << std::endl; 

    return 0; 
} 

그러나 컴파일이 실패했습니다 :

error: defining explicit specialization ’map<T>’ in friend delcaration 

은 어떻게 선언을 변경할 수 있습니다

void map(...){} // Worst case 

// Here's the class that will overload our function 
template<typename Type, typename T> 
struct MakeFunction { 
    friend Type map(T) { return {}; } 
}; 

// Make the function with int? 
struct MyType : MakeFunction<MyType, int> {}; 

int main() { 
    // The type obtained is void, worst case choosed. The expected result is `MyType` as return type. 
    std::cout << typeid(decltype(map(int{}))).name() << std::endl; 

    return 0; 
} 

을 그리고, 그 시도 올바른 함수가 선택 되었습니까? 아니면 토템을 사용하지 않고 유형을지도로 나타내는 방법이 있습니까? 코드 아래

+0

참고 : 우정은 (* 11.3/10 [class.friend] *에 따라) 상속되지 않습니다. – Holt

+0

'MakeFunction' 밖에서'map'을 정의 할 수 있습니까? – Holt

+0

'MakeFunction' 안에 정의하는 것이 포인트입니다. 확장 될 때마다 유형을 매핑하고 싶습니다. 나의 예에서,'MyType'은 그것을 확장하기 때문에, 지정된 타입을 가진'map' 함수를 사용할 수있게해야합니다. –

답변

3

는 매크로 DEFINE_TYPE_MAPPING 회의를 정의하는 방법을 보여줍니다 귀하의 요구 (이 어느 정도 생각을 보여주는 스케치입니다) :

#include <iostream> 
#include <typeinfo> 

void map(...){} // Worst case 

template<class T> struct TypeMapping; 

template<class T> 
typename TypeMapping<T>::type map(const T&); 

#define DEFINE_TYPE_MAPPING(T, U) \ 
    template<> struct TypeMapping<T> { typedef U type; }; 


struct MyType {}; 

DEFINE_TYPE_MAPPING(int, MyType); 
DEFINE_TYPE_MAPPING(char, float*); 
DEFINE_TYPE_MAPPING(std::ostream, unsigned long); 

int main() { 
    std::cout << typeid(decltype(map(int{}))).name() << std::endl; 
    std::cout << typeid(decltype(map('c'))).name() << std::endl; 
    std::cout << typeid(decltype(map(std::cout))).name() << std::endl; 
    std::cout << typeid(decltype(map(1.0))).name() << std::endl; 

    return 0; 
} 
+0

이것은 잘 작동 할 것입니다. 슬프게도, 나는 그것을위한 매크로를 만들 여유가 없다. 이것은 나보다 덜 제한적인 사람들을위한 좋은 대답입니다. –

+0

매크로가 짧고 간단하다는 것을 알 수 있습니다. 매크로의 기초가되는 코드를 작성할 수 있습니까? – Leon

2

방법에 대해 :

namespace detail{ 

    // To keep exact type 
    template <typename> struct tag {}; 

    // The mapping 
    float map(tag<char>); 
    MyType map(tag<int>); 
    char map(tag<const int&>); 
    // ... and so on 

} 

template <typename T> 
using map_t = decltype(detail::map(detail::tag<T>{})); 

그리고

int main() { 
    std::cout << typeid(map_t<int>).name() << std::endl; 
    std::cout << typeid(map_t<const int&>).name() << std::endl; 
} 
관련 문제