c++ - std::conditional 的可变模板使用,其中一种类型是实例化失败

标签 c++ templates c++11 variadic-templates template-meta-programming

我正在尝试构建一个可变模板类。通常,实例化的每一级都需要通过切掉一种类型然后使用其余类型来实例化“下一级”。对于我的最终级别,与其专注于一种类型,我宁愿提供一些基本案例类型并避免重复实际逻辑。

我添加了一个 std::conditional打开 BaseCase当其余类型由空参数包组成时。

class BaseCase { };

template <typename T, typename... Ts>
class VariadicClass;

template <typename... Ts>
using NextLevel = typename std::conditional<
    sizeof...(Ts) != 0, VariadicClass<Ts...>, BaseCase>::type;

template <typename T, typename... Ts>
class VariadicClass {
    T this_level; // whatever
    NextLevel<Ts...> next_level; // fails when Ts is empty
};

问题VariadicClass是基于至少一个类型参数的模板,所以当它达到基本情况时( Ts 为空),尝试使用 std::conditional使用 VariadicClass<> , 这当然会失败。

我的解决方案是编写一些特定的函数并使用 decltype与重载一起使用,而不是使用 std::conditional完全没有。

template <typename... Ts>
VariadicClass<Ts...> type_helper(Ts&&...);

BaseCase type_helper();

template <typename... Ts>
using NextLevel = decltype(type_helper(std::declval<Ts>()...));

现在,这行得通,但如果每次我有一个可变参数类时我都想保持这种做法,这似乎很乏味。有没有办法使用 std::conditional或类似的东西来实现这种效果而不必写出那么多针对特定问题的代码?

最佳答案

推迟评估。

template<class T>struct identity{
  template<class...>using result=T;
};
template<template<class...>class src>
struct delay{
  template<class...Ts>using result=src<Ts...>;
};

template <typename... Ts>
using NextLevel =
typename std::conditional<
  sizeof...(Ts) != 0, delay<VariadicClass>, identity<BaseCase>
>::type::template result<Ts...>;

identity 忽略 Ts... 并返回其参数。 delay 采用模板 并应用Ts...。虽然签名看起来很可疑,但它确实有效。

关于c++ - std::conditional 的可变模板使用,其中一种类型是实例化失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25539439/

相关文章:

c++ - 是否建议显式地使重写函数成为虚拟的?

c++ - 继承的成员函数似乎未声明,这是怎么回事?

c++ - 在泛型类之外定义函数会产生编译错误

c++11 - O(log n)中的c++ bitset逻辑运算?

c++ - 设置获取元素的位置

c++ - 对大文件有效的轻量级 XML 解析器?

c++ - 匿名命名空间

c++ - 没有为显式模板实例化请求提供合适的定义

c++ - 抛出 "bad_alloc"的最常见原因是什么?

c++ - 在 macOS 上从源代码构建 Qt 时出错