在阅读 C++11 Standard时,我注意到只有在满足某个条件时才定义20.8.3
三个s。typedef
通常如何编写这样的条件typedef
?
做到这一点的方法是通过部分专业化。考虑以下实现enable_if
(用于许多反射技巧,以及更多):
template <bool Condition, typename T>
struct enable_if {
typedef T type;
};
template <typename T>
struct enable_if<false, T> { /* no typedef */ };
只有当我传入一个评估为常量的typedef enable_if<...>::type
语句时才存在true
。例如:
typename enable_if<std::is_same<int, int>::value, int>::type; // = int
但
typename enable_if<std::is_same<int, long double>::value, int>::type; // = error. No typedef inside.
当您想为某种类型编写通用代码时,通常会使用此方法T
,但前提是T
具有某些属性,例如在 C++ 中,“替换失败不是错误”。例如
template <typename T, typename = enable_if<is_numeric<T>::value, int>::type>
struct Complex {
// impl...
};
通过插入任何T
非数字类型,我会得到一个编译器错误。它很脏,但它有效。
例如,像这样:
#include <type_traits>
namespace detail
{
template <class T, bool = std::is_integral<T>::value>
struct maybe_has_a_value_type_or_something_else_impl
{
using value_type = T;
};
template <class T>
struct maybe_has_a_value_type_or_something_else_impl<T, false>
{
using something_else = T;
};
} // namespace detail
template <class T>
struct maybe_has_a_value_type_or_something_else
: public detail::maybe_has_a_value_type_or_something_else_impl<T>
{
};
class Foo
{
};
int main()
{
maybe_has_a_value_type_or_something_else<int>::value_type a;
// maybe_has_a_value_type_or_something_else<int>::something_else b;
// maybe_has_a_value_type_or_something_else<Foo>::value_type c;
maybe_has_a_value_type_or_something_else<Foo>::something_else d;
}
LLVM 标头中使用了类似的实现__functional_base
。