Is there a way to ensure the template overload isn’t selected unless all other overloads fail, without resorting to enable_if?
Int should be handled by the long overload, but it’s being handled by the template overload, which the compiler doesn’t like.
class SetProxy {
public:
void operator=(const TemplateString& value) {
dict_.SetValue(variable_, value);
}
template<class T>
void operator=(const T& value) {
dict_.SetValue(variable_, TemplateString(value.data(), value.size()));
}
void operator=(long value) {
dict_.SetIntValue(variable_, value);
}
}
The problem with the code in the question is that the template is the best match if an argument convertible to
longorTemplateStringis passed: the template doesn’t need to do a conversion while calling the other functions would involve a conversion.The desired behavior can be achieved even without the use of
std::enable_ifalthough I think prohibiting the use ofstd::enable_ifis a made-up requirements: even if you can’t use C++2011 or Boost, it is extremely simple to implementstd::enable_if. Implementing some of the desired type traits is a bit harder but doable. Restricting its use effectively means that you’ll need to implement essentially the same logic in a more or less contrived way which doesn’t say what it really does. For example, this code doesn’t usestd::enable_ifor SFINAE but there is an extra object actually be created which wouldn’t be needed if SFINAE had been used:It doesn’t use the types from the original question because I don’t have them accessible and I didn’t feel like typing things irrelevant to the actual question. Note that this effectively contains the important bits of an implementation of
std::is_convertible. Internally, it is necessary to forward to another template because the assignment operator cannot have a variable argument list: since there are viable conversions frominttohelper<int>, there would be an ambiguity if there weren’t anything else to distinguish the types, a variable argument list is used to make the template version a bit worse.Just for reference, here is the in my opinion more readable version using
std::enable_if: