【问题标题】:Template specialization for type traits where the type change depending on conditional类型特征的模板特化,其中类型根据条件而改变
【发布时间】:2021-05-08 03:23:18
【问题描述】:

假设我们有一个给定的类ABC,它使用KV 进行模板化:

template <typename K, typename V>
using ABC = AnotherClass<K, V>

我知道可以实现类型特征来检查模板 T 是否属于给定类 ABC,例如:

template <typename T>
struct is_class_abc : std::false_type {};

template <typename K, typename V>
struct is_class_abc<ABC<K, V>> : std::true_type {};

假设我们将ABC 定义更改为AnotherClass,其类型会根据KV 而变化:

template <typename K, typename V>
using ABC = AnotherClass<typename std::conditional<
      CONDITION, SOMETHING, SOMETHIN_ELSE>::type, ... >

条件、something 和 something_else 都依赖并依赖于 K-V。

我得到这个编译错误:

类模板偏特化包含不能推导的模板参数;这个部分特化永远不会被使用

不可演绎的模板参数'K'

V 也一样。

知道是否可以这样做吗?如果是这样,我该如何让它发挥作用?

【问题讨论】:

  • 我们可以得到minimal reproducible example吗?
  • "class ABC" - 不是一个类。甚至没有类模板。别名的行为有些不同。
  • CONDITIONSOMETHINGSOMETHIN_ELSE 是否曾经使用过 KV
  • @RemyLebeau 是的。它有什么改变吗?
  • 我们能看到产生此错误消息的真实代码示例吗?诊断我们看不到的代码非常困难。

标签: c++ templates metaprogramming template-specialization typetraits


【解决方案1】:

部分特化不仅会检查传递的类型是否为ABC&lt;K,V&gt; 形式,还会尝试/需要推导KV。现在让我们看看这是如何工作的。假设我们通过类型特征应该检查ABC&lt;K, V&gt;。由于ABC 只是一个类型别名,因此传递给此类型特征的实际类型实际上是AnotherClass&lt;K',V'&gt; 形式,其中K'V'KV 的一些修改。

现在类型特征需要从K'V' 推导出KV,这是非常必要的,因为可能不存在这样的KV。但是由于您使用std::conditional&lt;...&gt;::type,因此编译器对那里发生的事情并不透明。这称为非推断上下文。基本上,有一些简单的情况我们可以向后推论(例如,如果你有ABC = AnotherClass&lt;const K, V&gt;)。在许多情况下(例如,当您在另一种类型中使用 typedef 时,例如这里),这很复杂/不可能。

这并不总是直观的,有时甚至令人费解,例如这里:

template<class>
struct is_const : std::false_type {};

template<class T>
struct is_const<const T> : std::true_type {}; // This works

template<class T>
struct is_const<typename add_const<T>::type> : std::true_type {}; // This does NOT work

第二个特化也只添加了一个常量,比如const T,但这是隐藏的(也就是在非推导上下文中),因此我们不能推导T

【讨论】:

  • 谢谢! tl;博士:所以这是不可能的,对吧?
  • 不可能。根据您正在做的事情,可能有一种解决方法,但不是一般性的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多