确定是否为特定类型的参数定义了重载函数

时间:2019-02-19 14:42:44

标签: c++ c++17

我有一个简单的序列化框架,该框架为各种类型(包括算术,我的类和std容器,例如向量,数组,映射等)定义了读写模板函数的专业化,因此可以做到

std::vector<std::string> v{ "a1", "b123", "c12345" };
Read(stream, v);
Write(stream, v);

std::map<int, MyClass> m;
Read(stream, m);
Write(stream, m);
例如

我正在寻找一种方法,可以通过实施类似的方法来确定在编译时是否可序列化的类型:

template <class T>
constexpr bool is_serializable()
{
    if (Read<T> and Write<T> are defined) 
        return true;
    return false;
}

或其他一些东西。

有可能吗?

读写声明:

    template <typename T>
    void Read(InputStream & s, T & val);

    template <typename T>
    void Write(OutputStream & s, T val);

从理论上讲,我可以为读写以外的每种类型定义is_serializable,但这需要更多类型的输入,并且可能使代码更复杂,因此自动定义is_serializable是一种更优雅的方法。

它也可以是一些具有读取和写入功能作为成员的序列化程序模板类。在这种情况下,我需要知道特定类型的序列化程序是否具有特殊化。例如,我可以使用它something like this

1 个答案:

答案 0 :(得分:4)

您可以使用std::void_t和SFINAE来实现。 cppreferencestd::void_t的文档很棒。

#include <type_traits>
#include <iostream>

void Read(std::istream &,double &) {}
void Write(std::ostream &,double) {}

template <typename T,typename= void>
struct is_serializable_t: std::false_type {};

template <typename T>
struct is_serializable_t<T,std::void_t<
    decltype(Read(std::declval<std::istream &>(),std::declval<T &>())),
    decltype(Write(std::declval<std::ostream &>(),std::declval<T>()))>>:
    std::true_type {};

template <typename T>
inline constexpr bool is_serializable = is_serializable_t<T>::value;

static_assert(is_serializable<double>);
static_assert(!is_serializable<int>);