考虑一下代码:
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)
您可以使用以下内容:
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)
#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