c++ 仅当匹配另一个模式时才匹配模板模式

ewm0tg9j  于 2023-01-28  发布在  其他
关注(0)|答案(3)|浏览(134)

我只为某些类型定义了一个模板函数:

template<typename T, std::enable_if_t<std::is_pod_v<T>, bool> = true >
void serialize(const T & t) { /*serialize POD*/ }

template<>
void serialize(const std::string  & t) { /*serialize string*/ }

//....

我还想添加一个std::vector专门化,它只在T可以序列化时才匹配

template<typename T /*, is_serializable<T> */>
void serialize(const std::vector<T> & t) { /*do something*/ }

我怎样才能使这个匹配只有当T自己匹配一个serialize()方法?

p5fdfcr1

p5fdfcr11#

对于C++20约束,您可以执行以下操作:

template <typename T>
void serialize(const std::vector<T>& v)
requires requires (T inner) {serialize(inner);}
{
  // serialize vector
  // ...
}

Demo

xytpbqjk

xytpbqjk2#

SFINAE变体可以简单到:

template<typename T, typename = decltype(serialize(std::declval<T>())) >
void serialize(std::vector<T> const& t)
{ /*do something*/ }
hs1rzwqc

hs1rzwqc3#

C++20之前的解决方案:测试是否可以序列化类型:

template <typename T>
auto is_serializable(T) -> decltype(serialize(std::declval<T>()), std::true_type());
std::false_type is_serializable(...);
template <typename T>
bool constexpr is_serializable_t
    = decltype(is_serializable(std::declval<T>()))::value;

这样,您就可以应用与POD类型相同的模式:

template<typename T, std::enable_if_t<is_serializable_t<T>, bool> = true >
void serialize(std::vector<T> const& t)
{ /*do something*/ }

godbolt上的演示。

根据注解编辑:

实际上,如果不序列化std::vector中包含的所有元素,序列化std::vector似乎没有意义。因此,最简单的解决方案(KISS原则...)是:只是 * 做 * 序列化而不添加任何测试!!!

template<typename T>
void serialize(std::vector<T> const& v)
{
    // you'd most likely need:
    serialize(v.size());
    // but other variants are be possible, too, like e.g. COBS encoding the data,
    // then last element to be added, when deserializing again, would be followed
    // by the sole 0 (or whatever other sentinel) character encountered...

    for(auto& t : v)
    {
        serialize(t);
    }
}

向量开始序列化它的元素,如果还有其他向量,这些元素也会做同样的事情--直到到达T不再是向量的基本情况,现在做出最终决定:是否存在处理这个最后的T的重载,从而代码是否编译;)
godbolt上的演示。

相关问题