I’ve a templatized class
template <typename T>
class Factors
{
public:
Factors(){};
deque<string> stringsDeck;
// some methods and variables here
map <string, string> getNext();
};
The getNext method combines a string used as key with the strings from stringsDeck used as value and returns a map <string,string>.
Provided that I have templatized stringify and string2num functions, I would like to have a method map<string,Scalar> getNext() which for every other type except from string acts converting the values of the map to the specified template type T.
The compiler doesn’t let me overload two methods with the same name but with different return type, specifically:
map <string, T > getNext()
{
// converts the values of getNext() return map into the specified type T
return convertedMapWithValuesOfTypeT;
}
What can be the solution in this case? I would like to keep the name of the method the same for string and other types (basically numerical types which can be converted from string via a lexical cast)
The language doesn’t allow function overloads which differ only on
return type, because in most cases, the return type isn’t considered in
function overload resolution. In this case, you really have three
possible solutions:
just to give the two functions different names:
getNextAsMapToTypeandgetNextAsMapToString, for example.then, specialize this function for
std::stringandT(and fornothing else). The user will have to specify
getNext<std::string>()or
getNext<...>to call the one he wants.Generally, I would find this considerably less readable than the
previous solution, but it might be applicable in templates, where
the names should contain or at least suggest the name of the type.
type, if you don’t mind some extra complexity. To do this, you still
have to implement one of the other solutions, but the client code
doesn’t see it. Basically, your
getNext()function must return aproxy, with overloaded conversion functions, something like:
class Proxy { Factors* myOwner; public: Proxy( Factors& owner ) : myOwner( &owner ) {} operator std::map<std::string, std::string>() const { return myOwner->getNextAsMapToString(); } operator std::map<std::string, T>() const { return myOwner->getNextAsMapToType(); } }; Proxy getNext() { return Proxy( *this ); }Client code can then just call
getNext(), and depending on what theydo with the results, either
getNextAsMapToStringorgetNextAsMapToTypewill be called.