views:

462

answers:

4

To test and display the result of some functions of my library, I am creating a set of handy functions.

I have an execute function that looks like :

template <typename R, typename I>
std::string execute( const std::string& func_name, R(*func_ptr)( const I& ), const I& func_input );

It calls the function, and display the results and arguments in a formatted string that I can send to std::cout.

The problem is that some of my functions do not return convertible-to-string results. I thought I could simply overload the global ::operator std::string with something like:

template <typename T>
operator std::string( const std::vector<T>& v );

But GCC complains:

error: 'operator std::string(const std::vector<T, std::allocator<_CharT> >&)' must be a nonstatic member function

Well, the problem of course is that I cannot add member operators to std::vector, and even for my classes, I don't want to pollute them with "for testing" conversion operators.

I guess that I can add a layer of indirection and use a function instead of a conversion operator, but that would not be the more aesthetic solution. I could also overload ::operator << for std::ostream and use a std::ostringstream, but that also is not the cleanest solution.

I wondered if the global conversion operator is really not overloadable, and if so, why.

+1  A: 

There is no user defined global conversion operator. You must control either the target type (in which case a non explicit one parameter constructor is the conversion operator) or the source type (in which case you have to overload the member operator target()).

AProgrammer
+3  A: 

I wondered if the global conversion operator is really not overloadable, and if so, why.

No, there is no such thing. Conversion functions must be a member of a class. If it weren't so, it would make overload resolution a particularly vexing problem for the compiler by introducing ambiguities.

dirkgently
But many operators are available as global or member, why not this one ? For instance, if there is a global and a member operator<<, the compiler complains for an ambiguous call, it could do the same thing with convertions.
Aurélien Vallée
Conversion functions are special member functions (as are the ctor, dtor, op= and copy-constructor) since they take part in conversions/object creation. See 12.3.
dirkgently
A: 

A conversion function must be a member function. The function may not specify a return type, and the parameter list must be empty. They should be used sparingly and there should be a clear conversion path from one type to another type. Otherwise they can lead to unexpected results and mysterious errors.

zdawg
+4  A: 

Conversion operators (cast operators) must be a member of the convertible class that produces the converted type. As assignment operators, they must be member functions, as your compiler is telling you.

Depending on how much effort you want to put into the debug part of it, you could try to use metaprogramming to forward your execute method to different actual implementations, providing specific ones for containers that will print the contents.

Why don´t you want to provide operator<< for your types? I think that is actually the idiomatic solution. Unlike other languages that you use methods that convert to string to produce printable results, in C++ the idiomatic way is providing operator<< and then using stringstreams (or boost::lexical_cast or some similar solution) to convert to strings based on the operator<< implementation. There is a simple utility class here to create a string from elements that override operator<< if you want to use that for a start point.

David Rodríguez - dribeas