On 6/25/2012 10:07 AM, Gerhard Fiedler wrote:
Victor Bazarov wrote:
This:
---------------------------------------------->8 cut here
#include<iostream>
#include<type_traits>
#include<string>
template<typename T>
class is_printable
{
typedef char yes[1];
typedef char no[2];
template<typename C> static yes& test( decltype(&C::print) );
template<typename C> static no& test(...);
public:
static const bool value = (sizeof(test<T>(0)) == sizeof(yes));
};
template<> class is_printable<std::string> {
public: static const bool value = false;
};
template< class Printable>
typename
std::enable_if<is_printable<Printable>::value,std::ostream&>::type
operator<<( std::ostream&stream, Printable const&printable )
{
printable.print( stream );
return stream;
}
class MyClass
{
public:
MyClass( char const *val ) : str( val ) {}
void print( std::ostream&stream ) const { stream<< str; }
private:
char const *str;
};
template<typename T>
void GTestStreamToHelper(std::ostream* os, const T& val) {
*os<< val;
}
int main()
{
MyClass foo( "bar" );
std::cout<< "test "<< foo<< std::endl;
std::string const gtest( "gtest" );
GTestStreamToHelper(&std::cout, gtest );
std::cout<< std::endl;
}
---------------------------------------------->8 cut here
compiled for me fine with Visual C++ 2010. And the output was
test bar
gtest
Does that solve your problem?
I see... thanks for following up on this.
I can't (yet) tell whether this solves my problem -- because don't (yet)
understand how this works, and what I may have to do to make it work
generally.
When GTestStreamToHelper is used with T=std::string, it looks for an
operator<<( std::ostream&stream, std::string const& ), right? Why
doesn't it pick the right one, without explicit help? Shouldn't the
generic definition of is_printable tell it that std::string doesn't have
a print() member function?
The whole idea behind is_printable is that it is /automatically/ false
for classes that don't provide a print() member function. I don't
understand why it is necessary to explicitly tell the compiler that
std::string doesn't have one if it already knows this... Can somebody
please explain why this is necessary?
If I have to provide such an explicit "false" declaration for every
class that may be used as T with GTestStreamToHelper (and with any other
template function that may use an ostream operator<<), for me this
doesn't work.
My guess is that 'is_printable' is at fault. Comment out the operator<<
, the Google stuff, and replace your main with this:
int main()
{
std::cout << "MyClass : "
<< (is_printable<MyClass>::value ?
"printable" : "not printable") << std::endl;
std::cout << "std::string : "
<< (is_printable<std::string>::value ?
"printable" : "not printable") << std::endl;
}
and what do you get? I get that both are 'printable'. Need to debug the
'is_printable' template. Looking into it...
Check out http://www.gockelhut.com/c++/articles/has_member .
built-in types. Then I found that page, but lack the time and
motivation to study it at the proper depth...