Home > Mobile >  C conditional execution depending on the type
C conditional execution depending on the type

Time:11-07

I have a template function that should execute different code, depends on the type. The simplified function looks like this:

template<typename T>
std::string test(T value)
{
    std::string v;
    if(std::is_arithmetic<T>())
    {
        v = std::to_string(value);
    }
    else
    {
       v = std::string(value);
    }
    return v;
}

Usage:

test("Hello");
test(123);

But I get this error:

In instantiation of void test(T) [with T = const char*]:
error: no matching function for call to to_string(const char*)
note: candidate: std::string std::__cxx11::to_string(int) <near match>
to_string(int __val)

and the same for the following:

to_string(unsigned __val)
to_string(long __val)
to_string(unsigned long __val)

Ok, I understand that in case of, for example const char * the compilation will fail since there is no std::to_string(const char *). but how can I do the code works? Just have to note that in my real code I limit to c 11.

CodePudding user response:

You now get a taste of why if constexpr was added to the language. If you need to perform some type-dependent operation as part of your larger algorithm, then in pre-C 17 the way to do that is typically via tag-dispatch

namespace detail {
    template<typename T>
    std::string stringify(T value, std::true_type) {
        return std::to_string(value);
    }
    template<typename T>
    std::string stringify(T value, std::false_type) {
        return std::string(value);
    }
}

template<typename T>
std::string test(T value)
{
    std::string v;
    v = detail::stringify(value, std::is_arithmetic<T>());
    return v;
}

This is dispatching on two conditions, but the technique can be expanded to multiple overloads, depending on how you construct your tag types. A common example in the standard is iterator categories.

CodePudding user response:

You can apply overloading with SFINAE. E.g.

// for arithmetic types
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value, std::string>::type test(T value)
{
    std::string v;
    v = std::to_string(value);
    return v;
}

// for non-arithmetic types
template<typename T>
typename std::enable_if<!std::is_arithmetic<T>::value, std::string>::type test(T value)
{
    std::string v;
    v = std::string(value);
    return v;
}
  • Related