模板:未申请 SFINAE 专业化
Templates: SFINAE specialization not getting applied
下面的代码片段,至少我认为,是 SFINAE 应用于专业化的尽可能直接的示例。
最后一行是重点,也是故障发生的地方。专门的 foo
模板的定义决定了 bar
模板的专门化,或者我想要的。其他 bar
专业化可以在别处定义,或者可能只是不支持任意类型的使用。
据我了解,enable_if
广泛建议使用相同的模式。
template <typename T>
struct foo;
template <>
struct foo<int> {
using type = int;
};
template <typename T, typename use = void>
struct bar;
template <typename T>
struct bar<T, typename foo<T>::type> {
using type = typename foo<T>::type;
};
using good = typename foo<int>::type;
using bad = typename bar<int>::type;
在g++中,14或17标准,结果如下所示。似乎没有应用 bar
专业化,编译器正在使用非专业化(空)定义。为什么?
$ g++ --std=c++14 special.cpp -o special
special.cpp:18:32: error: ‘type’ in ‘struct bar<int>’ does not name a type
using bad = typename bar<int>::type;
template <typename T>
struct bar<T, typename foo<T>::type> {
using type = typename foo<T>::type;
};
应该是
template <typename T>
struct bar<T, std::void_t<typename foo<T>::type>> {
using type = typename foo<T>::type;
};
因为 use
应该总是 void
.
这就是为什么命名为 AlwaysVoid
会更好。
(或将其角色用作 Enabler
)
template <typename T, typename AlwaysVoid = void>
struct bar;
下面的代码片段,至少我认为,是 SFINAE 应用于专业化的尽可能直接的示例。
最后一行是重点,也是故障发生的地方。专门的 foo
模板的定义决定了 bar
模板的专门化,或者我想要的。其他 bar
专业化可以在别处定义,或者可能只是不支持任意类型的使用。
据我了解,enable_if
广泛建议使用相同的模式。
template <typename T>
struct foo;
template <>
struct foo<int> {
using type = int;
};
template <typename T, typename use = void>
struct bar;
template <typename T>
struct bar<T, typename foo<T>::type> {
using type = typename foo<T>::type;
};
using good = typename foo<int>::type;
using bad = typename bar<int>::type;
在g++中,14或17标准,结果如下所示。似乎没有应用 bar
专业化,编译器正在使用非专业化(空)定义。为什么?
$ g++ --std=c++14 special.cpp -o special
special.cpp:18:32: error: ‘type’ in ‘struct bar<int>’ does not name a type
using bad = typename bar<int>::type;
template <typename T>
struct bar<T, typename foo<T>::type> {
using type = typename foo<T>::type;
};
应该是
template <typename T>
struct bar<T, std::void_t<typename foo<T>::type>> {
using type = typename foo<T>::type;
};
因为 use
应该总是 void
.
这就是为什么命名为 AlwaysVoid
会更好。
(或将其角色用作 Enabler
)
template <typename T, typename AlwaysVoid = void>
struct bar;