Re: Template functions and avoiding implicit conversions
On 27 Feb., 14:56, "tarjei.knaps...@gmail.com"
<tarjei.knaps...@gmail.com> wrote:
Consider the following:
class CommandLineOptions
{
public:
template <typename ValueType>
void
Add(std::string& arg, bool required);
template <typename ValueType>
void
Add(std::string& arg, ValueType default);
default is a keyword, which is not allowed in this
context. I assume def instead.
};
The problem I have is that if I write something like:
CommandLineOptions clo;
clo.Add<std::string>("method", "invert");
This cannot compile, because the string literal does
not convert to a std::string&. I assume the following
code instead:
std::string s("method");
clo.Add<std::string>(s, "invert");
the second argument is implicitly converted to bool and the first
template function is instantiated.
The possible resolutions I've come up with are:
1. Rename the first function to for instance AddRequired(). I'd like
to avoid this to keep the interface as simple as possible.
2. Require the user to explicitly instantiate a std::string in the
call,
clo.Add<std::string>("method", std::string("invert"));. This is far
too error prone and not really a solution at all.
Is there any other neat trick I could use to avoid the implicit
conversion from happening?
You can use SFINAE ("Substitution Failure Is Not An Error") here
to distinguish between both overloads.
template <bool enable, typename T = void>
struct EnableIf {
typedef T Type;
};
template <typename T>
struct EnableIf<false, T> {
};
template <typename T>
struct IsBool {
static const bool value = false;
};
template <>
struct IsBool<bool> {
static const bool value = true;
};
class CommandLineOptions
{
public:
template <typename ValueType>
typename EnableIf<IsBool<ValueType>::value>::Type
Add(std::string& arg, ValueType required);
template <typename ValueType>
typename EnableIf<!IsBool<ValueType>::value>::Type
Add(std::string& arg, ValueType def);
};
int main() {
CommandLineOptions clo;
std::string s("method");
clo.Add<std::string>(s, "invert"); // Selects 2nd overload
clo.Add(s, "invert"); // Selects 2nd overload
clo.Add<bool>(s, true); // Selects 1st overload
clo.Add(s, false); // Selects 1st overload
clo.Add<std::string>(s, true); // Does not compile
}
Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]