Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid "conditional expression is constant" warning with compile-time-constant conditions in template code?

Tags:

c++

templates

Consider the code:

template <typename T>
CByteArray serialize(const T& value)
{
    if (std::is_pod<T>::value)
        return serializePodType(value);
    else if (std::is_convertible<T, Variant>::value)
        return serialize(Variant(value));
    else
    {
        assert(0 == "Unsupported type");
        return CByteArray();
    }
}

Obviously, the compiler is right to give me this warning for if (std::is_pod<T>::value) etc., but how do I circumvent this? I can't find a way to avoid this check, and there's no static if in C++ (yet).

Can SFINAE principle be used to avoid this if?

like image 769
Violet Giraffe Avatar asked Oct 31 '14 13:10

Violet Giraffe


3 Answers

Can SFINAE principle be used to avoid this if?

Yes, at least for the non-default cases:

template <typename T>
typename std::enable_if<std::is_pod<T>::value, CByteArray>::type 
serialize(const T& value)
{
    return serializePodType(value);
}

template <typename T>
typename std::enable_if<
    !std::is_pod<T>::value &&    // needed if POD types can be converted to Variant
    std::is_convertible<T, Variant>::value, CByteArray>::type 
serialize(const T& value)
{
    return serialize(Variant(value));
}

If you want a run-time, rather than compile-time, error for unsupported types, then declare a variadic function to catch any arguments that don't match the other overloads.

CByteArray serialize(...)
{
    hlassert_unconditional("Unsupported type");
    return CByteArray();
}
like image 94
Mike Seymour Avatar answered Nov 06 '22 10:11

Mike Seymour


You may use something like:

template <typename T> CByteArray serialize(const T& value);

namespace detail
{
    template <typename T>
    CByteArray serializePod(const T& value, std::true_type);
    {
        return serializePodType(value);
    }

    template <typename T>
    CByteArray serializePod(const T& value, std::false_type);
    {
        static_assert(std::is_convertible<T, Variant>::value, "unexpect type");
        return serialize(Variant(value));
    }
}

template <typename T>
CByteArray serialize(const T& value)
{
    return detail::serializePod(value, std::is_pod<T>{});
}
like image 6
Jarod42 Avatar answered Nov 06 '22 12:11

Jarod42


I'd be tempted to leave it as is, frankly. The compiler is demonstrating that it knows the unused branches can be optimised away. Sure, the warning is a bit of a drag, but ..

Anyway, if you really want to do this, use std::enable_if on the function's return type.

like image 5
Lightness Races in Orbit Avatar answered Nov 06 '22 10:11

Lightness Races in Orbit