类型特征的模板特化,其中类型根据条件改变

Template specialization for type traits where the type change depending on conditional

假设我们有一个给定的 class ABC,它的模板是 KV:

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

我知道可以实现类型特征来检查模板 T 是否属于给定的 class 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_else都依赖于K-V

我得到这个编译错误:

Class template partial specialization contains template parameters that cannot be deduced; this partial specialization will never be used

Non-deducible template parameter 'K'

V 相同。

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

偏特化不仅会检查传递的类型是否为 ABC<K,V> 形式,还会 try/need 推导 KV。现在让我们看看它是如何工作的。假设我们传递类型特征应该检查 ABC<K, V>。由于 ABC 只是类型别名,因此传递给此类型特征的实际类型实际上是 AnotherClass<K',V'> 形式,其中 K'V' 是 [=12 的一些修改=] 和 V.

现在类型特征需要从K'V'推导出KV,这确实是必要的,因为有可能没有例如 KV。但是由于您使用了 std::conditional<...>::type,因此对于编译器来说那里发生的事情并不透明。这称为非推导上下文。基本上,在一些简单的情况下我们可以向后推导(例如,如果你有 ABC = AnotherClass<const K, V>)。在许多情况下(例如当您在另一个类型中使用 typedef 时,就像这里一样)这是可能的 complicated/not。

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

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,例如 const T,但这是隐藏的(也就是在非推导上下文中),因此我们无法推导 T.