变量模板化使用std :: conditional,其中一种类型是实例化失败

Rya*_*ing 4 c++ templates template-meta-programming variadic-templates c++11

我试图建立一个变量模板类.通常,实例化的每个级别需要通过切掉一个类型然后使用余数来实例化"下一级".对于我的最终级别,而不是专注于一种类型,我宁愿给出一些基本案例类型,并避免重复实际逻辑.

我添加了一个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
};
Run Code Online (Sandbox Code Playgroud)

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

现在,这是有效的,但如果我想每次有一个变量类时都要保持这种练习,那看起来很乏味.有没有办法使用std::conditional或类似的东西来实现这种效果,而无需写出这么多特定于问题的代码?

Yak*_*ont 6

推迟评估.

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

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