Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing SFINAE to check for global operator<<?
    text
    copied!<p>I want to have several overloaded, global <code>to_string()</code> functions that take some type <code>T</code> and convert it to its string representation. For the general case, I want to be able to write:</p> <pre><code>template&lt;typename T,class OutputStringType&gt; inline typename enable_if&lt;!std::is_pointer&lt;T&gt;::value &amp;&amp; has_insertion_operator&lt;T&gt;::value, void&gt;::type to_string( T const &amp;t, OutputStringType *out ) { std::ostringstream o; o &lt;&lt; t; *out = o.str(); } </code></pre> <p>My implementation of <code>has_insertion_operator</code> so far is:</p> <pre><code>struct sfinae_base { typedef char yes[1]; typedef char no[2]; }; template&lt;typename T&gt; struct has_insertion_operator : sfinae_base { template&lt;typename U&gt; static yes&amp; test( U&amp; ); template&lt;typename U&gt; static no&amp; test(...); static std::ostream &amp;s; static T const &amp;t; static bool const value = sizeof( test( s &lt;&lt; t ) ) == sizeof( yes ); // line 48 }; </code></pre> <p>(It borrows from <a href="https://stackoverflow.com/questions/257288/">this</a> and <a href="https://stackoverflow.com/questions/4434569/">this</a>.) That seems to work. But now I want to have an overloaded version of <code>to_string</code> for types that do <em>not</em> have <code>operator&lt;&lt;</code> but <em>do</em> have their own <code>to_string()</code> <em>member</em> function, i.e.:</p> <pre><code>template&lt;class T,class OutputStringType&gt; inline typename enable_if&lt;!has_insertion_operator&lt;T&gt;::value &amp;&amp; has_to_string&lt;T,std::string (T::*)() const&gt;::value, void&gt;::type to_string( T const &amp;t, OutputStringType *out ) { *out = t.to_string(); } </code></pre> <p>The implementation of <code>has_to_string</code> is:</p> <pre><code>#define DECL_HAS_MEM_FN(FN_NAME) \ template&lt;typename T,typename S&gt; \ struct has_##FN_NAME : sfinae_base { \ template&lt;typename SignatureType,SignatureType&gt; struct type_check; \ template&lt;class U&gt; static yes&amp; test(type_check&lt;S,&amp;U::FN_NAME&gt;*); \ template&lt;class U&gt; static no&amp; test(...); \ static bool const value = sizeof( test&lt;T&gt;(0) ) == sizeof( yes ); \ } DECL_HAS_MEM_FN( to_string ); </code></pre> <p>(This part seems to work fine. It's adapted from <a href="https://stackoverflow.com/questions/257288/">this</a>.) However, when I have:</p> <pre><code>struct S { string to_string() const { return "42"; } }; int main() { string buf; S s; to_string( s, &amp;buf ); // line 104 } </code></pre> <p>I get:</p> <pre><code>foo.cpp: In instantiation of ‘const bool has_insertion_operator&lt;S&gt;::value’: foo.cpp:104: instantiated from here foo.cpp:48: error: no match for ‘operator&lt;&lt;’ in ‘has_insertion_operator&lt;S&gt;::s &lt;&lt; has_insertion_operator&lt;S&gt;::t’ </code></pre> <p>It seems like SFINAE is not happening. How do I write <code>has_insertion_operator</code> correctly such that it determines whether a global <code>operator&lt;&lt;</code> is available?</p> <p>FYI: I'm using g++ 4.2.1 (that which ships as part of Xcode on Mac OS X). Also, I'd like the code to be only standard C++03 without 3rd-party libraries, e.g., Boost.</p> <p>Thanks!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload