简体   繁体   English

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

[英]Variadically templated use of std::conditional where one type is an instantiation failure

I am attempting to build a variadically templated class. 我试图建立一个变量模板类。 As is common, each level of the instantiation needs to instantiate the "next level" by slicing off one type and then using the remainder. 通常,实例化的每个级别需要通过切掉一个类型然后使用余数来实例化“下一级”。 For my final level, rather than specialize on one type, I'd rather give some base case type and keep from duplicating the actual logic. 对于我的最终级别,而不是专注于一种类型,我宁愿给出一些基本案例类型,并避免重复实际逻辑。

I've added a std::conditional to switch on the BaseCase when the rest of the types consists of an empty parameter pack. 当其余类型包含一个空参数包时,我添加了一个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
};

The problem is that VariadicClass is templated on at least one type parameter, so when it hits the base case ( Ts is empty), trying to use std::conditional uses VariadicClass<> , which fails of course. 问题VariadicClass是至少一个类型参数的模板,所以当它遇到基本情况( Ts为空)时,尝试使用std::conditional使用VariadicClass<> ,当然这是失败的。

The solution I've managed is to write some specific functions and use decltype along with overloads, and not use std::conditional at all. 我管理的解决方案是编写一些特定的函数并使用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>()...));

Now, this works, but if I want to keep up this practice every time I have a variadic class, it seems tedious. 现在,这是有效的,但如果我想每次有一个变量类时都要保持这种练习,那看起来很乏味。 Is there a way to use std::conditional or something similar to achieve this effect without having to write out so much problem-specific code? 有没有办法使用std::conditional或类似的东西来实现这种效果,而不必写出这么多特定于问题的代码?

Defer evaluation. 推迟评估。

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 ignores the Ts... and returns its argument. identity忽略Ts...并返回其参数。 delay takes a template and applies the Ts... . delay采用template并应用Ts... While the signature looks suspicious, it works. 虽然签名看起来很可疑,但它确实有效。

Why not just 为什么不呢

class BaseCase { };

template <typename... Ts>
class VariadicClass; // undefined base template

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

template <typename T, typename... Ts>
class VariadicClass<T, Ts...> { // partial specialization for having at least 1 type parameter
    T this_level; // whatever
    NextLevel<Ts...> next_level;
};

After reading TC's answer and Yakk's comment, I realized I could write this as one templated class with two specializations, rather than write another BaseClass and the type alias. 在阅读了TC的答案和Yakk的评论之后,我意识到我可以将它写成一个带有两个特化的模板化类,而不是编写另一个BaseClass和类型别名。

template <typename... Ts>
class VariadicClass;

// specialization gets everything but an empty Ts
template <typename T, typename... Ts>
class VariadicClass<T, Ts...> {
    VariadicClass<Ts...> next_level;
    // normal case
};

template <>
class VariadicClass<> { // instead of class BaseCase
    // base case
};

Alternatively, you may specialize VariadicClass<T> 或者,您可以专门化VariadicClass<T>

class BaseCase {};

// general case
template <typename T, typename... Ts>
class VariadicClass {
    T this_level; // whatever
    VariadicClass<Ts...> next_level;
};

// specialization
template <typename T>
class VariadicClass<T> {
    T this_level; // whatever
    BaseClass next_level;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM