2013-05-13 19 views
6

Using SFINAE to check for global operator<<? ve templates, decltype and non-classtypes gelen bilgilerin toplanması, ben aşağıdaki kodu var beyan veya aksi halde to_string yöntemini çağırmak.type_traits std ile segmentasyon hatası :: dize

struct Foo 
{ 
public: 
    friend std::ostream& operator<<(std::ostream & os, Foo const& foo); 
}; 

struct Bar 
{ 
public: 
    std::string to_string() const 
    { 
     return "from to_string()"; 
    } 
}; 

Ve Test çıkışı:

Sonra sınıfları yüzden gibidir 1

namespace has_insertion_operator_impl { 
    typedef char no; 
    typedef char yes[2]; 

    struct any_t { 
    template<typename T> any_t(T const&); 
    }; 

    no operator<<(std::ostream const&, any_t const&); 

    yes& test(std::ostream&); 
    no test(no); 

    template<typename T> 
    struct has_insertion_operator { 
    static std::ostream &s; 
    static T const &t; 
    static bool const value = sizeof(test(s << t)) == sizeof(yes); 
    }; 
} 

template<typename T> 
struct has_insertion_operator : 
    has_insertion_operator_impl::has_insertion_operator<T> { 
}; 

soru 2

template <typename T> 
typename std::enable_if<has_insertion_operator<T>::value, T>::type 
print(T obj) { 
    std::cout << "from print()" << std::endl; 
} 

template <typename T> 
typename std::enable_if<!has_insertion_operator<T>::value, T>::type 
print(T obj) { 
    std::cout << obj.to_string() << std::endl; 
} 

Alındığı soruya Alındığı

int main() 
{ 
    print<Foo>(Foo()); 
    print<Bar>(Bar()); 

    //print<Bar>(Foo()); doesn't compile 
    //print<Foo>(Bar()); doesn't compile 

    print(Foo()); 
    print(Bar()); 

    print(42); 
    print('a'); 
    //print(std::string("Hi")); seg-fault 
    //print("Hey"); 
    //print({1, 2, 3}); doesn't compile 
    return 0; 
} 

print(std::string("Hi")); satır segmenti hataları. Birisi bana nedenini söyleyebilir mi?

+2

:

sadece std::enable_if ikinci şablon bağımsız değişken olarak bir türünü belirten kaçınmak veya void belirtin C++ 03 ile çalışıyorsanız ve işlev şablon parametreleri için varsayılan argümanlar belirtmek yapamıyorsanız Bu kadar hevesle dağıttığın için bitti mi? :) – jrok

+0

@jrok: "İyi-ama-düşük-iyi kullanıcılar nasıl tedavi edilir?" Türünde bir deneyi seziyorum ... –

cevap

7

Her iki işleviniz de print() öğesinin bir şey döndürmesi beklenir, ancak bunun yerine hiçbir şey döndürmezsiniz (Q & bağlandığınız sürümlerin aksine). Bu, C++ 11 Standardının 6.6.3/2. paragrafı başına tanımlanmamış bir davranıştır. print() Eğer

şey dönmek o void dönelim ve şablon parametre listesinde SFINAE kısıtlamayı koymamalıydın edilir:

İşte
template <typename T, 
    typename std::enable_if< 
     has_insertion_operator<T>::value, T>::type* = nullptr> 
void print(T obj) { 
    std::cout << "from print()" << std::endl; 
} 

template <typename T, 
    typename std::enable_if< 
     !has_insertion_operator<T>::value, T>::type* = nullptr> 
void print(T obj) { 
    std::cout << obj.to_string() << std::endl; 
} 

yukarıdaki Değişikliği içeren bir live example olduğunu. Temsilcinizden ilgisi var

template <typename T> 
typename std::enable_if<has_insertion_operator<T>::value>::type 
print(T obj) { 
    std::cout << "from print()" << std::endl; 
} 

template <typename T> 
typename std::enable_if<!has_insertion_operator<T>::value>::type 
print(T obj) { 
    std::cout << obj.to_string() << std::endl; 
} 
+0

Bu, ikinci, varsayılan şablon parametresinde 'enable_if' kullanılarak ve' void' döndürülerek giderilemedi? – dyp

+0

"typename enable_if" satırının dönüş değeri olduğunu anlamak biraz zamanımı aldı. –

+0

@DyP: Aklımı okuyorsunuz, sadece cevabı düzenliyordum;) –

İlgili konular