2016-06-21 1 views
0

与えられた型の挿入演算子があることを検出したいと思います。通常は、適切な署名で過負荷関数が存在することを確認します。私はクラスAを持っているとします。C++特定の型を受け入れる名前で関数が存在するかどうかを検出します。

template<typename T> 
struct insert_operator_type 
{ 
    using type = typename std::ostream&(*)(std::ostream&, const T&); 
}; 
... 
std::is_same< 
     decltype(static_cast<typename insert_operator_type<A>::type> (&operator<<)), 
     std::ostream&(*)(std::ostream&, A const&) 
    >::value 

私はそれが同じで、私は演算子が存在すると推測できます。オペレータと< <は、しかし、それはタイプBが言うタイプAに今

template<typename T> 
class A 
{ 
public: 
    T* type1 = nullptr; 
}; 

typedef A<int> BImpl; 

class B : public BImpl 
{ 
public: 

    B() {} 
}; 

template<typename T> 
std::ostream& operator<<(std::ostream& os, const A<T>& a) 
{ 
    os << "printing A<T>" << std::endl; 
    return os; 
} 

私はでき

B b; 
std::cout << b << std::endl; 

のようなものを解決している可能性がありますしかし、その代わりに何

std::ostream&(*)(std::ostream&, B const&) 

コンパイラありませんBImplバージョンを使用するようになり、イディオムはBの挿入演算子があることを識別することができません。

関数が特定の型に対して指定されないかもしれないが、特定の型が指定された型に変換されるような、多重定義された関数が存在すると判断できますか?

+0

私は 'B'は、私だけのための1つを見るために挿入演算子を見ていない '' – vu1p3n0x

答えて

4

おそらく、挿入を行っている式全体が有効かどうかを確認するためにSFINAEを使用するだけです。

// std::void_t in C++1z 
template <class...> 
using void_t = void; 

template <class, class = void_t<>> 
struct can_be_ostreamed : std::false_type { }; 

template <class T> 
struct can_be_ostreamed<T, void_t< 
    decltype(std::declval<std::ostream&>() << std::declval<T>()) 
>> : std::true_type { }; 

Live on Coliru

+0

あなたがのstd :: declval <>ここで何をしているか説明できますか? –

+0

@MichaelConlen 'std :: declval'は、実際にインスタンスを構築することなく、任意の型の式を取得するために使用されます(アクセスできないコンストラクタのために問題になる可能性があります)。 'decltype'のような評価されていないコンテキストでのみ使用できます。 – Quentin

+0

これはgcc 4で壊れていて、can_be_ostreamed > ::値がtrueであることを発見しなければならないが、これはうまくいくように見える。 –

関連する問題