Type_traits segmentation error with std :: string

Gathering information from Using SFINAE to validate global operator patterns <? and decltype and non-classtypes , I got the following code:

http://ideone.com/sEQc87

Basically, I combined the code from both questions to call the print function if it has an ostream , or else to call the to_string method.

Adapted from Question 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> { }; 

Adapted from Question 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; } 

Then my classes will be like this:

 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()"; } }; 

And the test output:

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

Error Segments print(std::string("Hi")); . Can someone tell me why?

+6
source share
1 answer

Both of your print() functions should return something, but instead return nothing (unlike the versions in Q & As you linked). This behavior is undefined in accordance with clause 6.6.3 / 2 of the C ++ 11 standard.

If print() should not return anything, let it return void and place the SFINAE constraint in the list of template parameters:

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

Here is a live example containing the above change.

If you work with C ++ 03 and cannot specify default arguments for function template parameters, simply do not specify the type as the second argument of the std::enable_if or specify void :

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

Source: https://habr.com/ru/post/944909/


All Articles