2016-06-14 14 views
2

私はテンプレート構造内の関数をfriendを使ってオーバーロードしようとしています。 タイプを別のタイプにマップするために、それを使用したいと思います。以下のコードでは、タイプintMyTypeにマップしたいと考えています。テンプレートフレンド関数:間違った関数が呼び出されました

は、ここで私はこれまでやったことだ:

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; 
} 

その後、私がすることを試みた:

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 

どのように宣言を変更することができます正しい関数が選択されていますか?または、ボイラープレートなしで型をマップする方法はありますか?コードの下

+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; 
} 
関連する問題