如何在模板代码中使用编译时常量条件避免"条件表达式是常量"警告?

Vio*_*ffe 15 c++ templates

考虑一下代码:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,编译器给我这个警告if (std::is_pod<T>::value)等是正确的,但是我该如何规避呢?我找不到避免这种检查的方法,而且static if在C++中还没有.

可以使用SFINAE原则来避免这种情况if吗?

Mik*_*our 10

如果可以使用SFINAE原则来避免这种情况吗?

是的,至少对于非默认情况:

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));
}
Run Code Online (Sandbox Code Playgroud)

如果您想要不受支持的类型的运行时而不是编译时错误,那么声明一个可变参数函数来捕获与其他重载不匹配的任何参数.

CByteArray serialize(...)
{
    hlassert_unconditional("Unsupported type");
    return CByteArray();
}
Run Code Online (Sandbox Code Playgroud)


Jar*_*d42 6

您可以使用以下内容:

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>{});
}
Run Code Online (Sandbox Code Playgroud)


Lig*_*ica 5

坦率地说,我很想放弃它.编译器证明它知道可以优化掉未使用的分支.当然,警告有点拖累,但..

无论如何,如果你真的想这样做,请使用std::enable_if函数的返回类型.


Ben*_*ers 5

怎么样?http://ideone.com/WgKAju

#include <cassert>
#include <type_traits>
#include <iostream>

class CByteArray { public: CByteArray() {}};

class Variant {};

template<typename T>
CByteArray serializePodType(const T&)
{
    printf("serializePodType\n");
    return CByteArray();
}

CByteArray serializeVariant(const Variant& v)
{
    printf("serializeVariant\n");
    return CByteArray();
}

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_convertible<T, Variant>::value && !std::is_pod<T>::value, CByteArray>::type serialize(const T& value)
{
    return serializeVariant(Variant(value));
}

class ConvertibleToVariant : public Variant { virtual void foo(); };

struct POD {};

struct NonPOD { virtual void foo(); };

int main()
{
    POD pod;
    ConvertibleToVariant ctv;
    //NonPOD nonpod;

    const auto ctv_serialised = serialize(ctv);
    const auto pod_serialised = serialize(pod);
    //const auto nonpod_serialised = serialize(nonpod);
}
Run Code Online (Sandbox Code Playgroud)

这个文档很适合enable_if:http://en.cppreference.com/w/cpp/types/enable_if