2016-06-21 5 views
0

Ich möchte erkennen, dass es einen Einfügeoperator für einen bestimmten Typ gibt. Normalerweise würde ich überprüfen, ob eine überladene Funktion mit der richtigen Signatur existiert. Sagen, dass ich eine Klasse A haben, dannC++ Ermitteln, ob es eine Funktion nach Name gibt, die einen bestimmten Typ akzeptiert

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 

mir sagen, werden sie gleich sind, und ich kann ableiten, dass der Bediener vorhanden ist. Mit Operator < < jedoch ist es möglich, dass ein Typ B ein Typ A. löst sich in etwas sagen wie

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

Jetzt kann ich

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

Aber es gibt keine

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

anstelle der Compiler stellt fest, dass die BImpl-Version verwendet wird und das Idiom nicht erkennt, dass es einen Einfügungsoperator für B gibt.

Kann ich feststellen, dass eine überladene Funktion vorhanden ist, so dass die Funktion möglicherweise nicht für einen bestimmten Typ angegeben wird, aber für einen Typ, den der angegebene Typ konvertiert?

+0

Ich sehe eine Einfügeoperator nicht für 'B', ich sehe man nur für 'A ' – vu1p3n0x

Antwort

4

Sie möchten wahrscheinlich nur SFINAE verwenden, um zu überprüfen, ob der gesamte Ausdruck, der die Einfügung durchführt, gültig ist.

// 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

Können Sie erklären, was std :: declval <> hier tut? –

+0

@MichaelConlen 'std :: declval' wird verwendet, um einen Ausdruck beliebigen Typs zu erhalten, ohne eine Instanz tatsächlich konstruieren zu müssen (was aufgrund eines nicht zugänglichen Konstruktors problematisch sein könnte). Es kann nur in nicht evaluierten Kontexten wie 'decltype' verwendet werden. – Quentin

+0

So sieht es aus, als ob das funktioniert, obwohl ich feststellen musste, dass es in gcc 4 kaputt ist und meldet, dass can_be_ostreamed > :: value ist true. –

Verwandte Themen