为了学习如何使用Eric Niebler的ranges v3库,并阅读源代码,我看到了这个宏定义:
#define CONCEPT_PP_CAT_(X, Y) X ## Y
#define CONCEPT_PP_CAT(X, Y) CONCEPT_PP_CAT_(X, Y)
/// \addtogroup group-concepts
/// @{
#define CONCEPT_REQUIRES_(...) \
int CONCEPT_PP_CAT(_concept_requires_, __LINE__) = 42, \
typename std::enable_if< \
(CONCEPT_PP_CAT(_concept_requires_, __LINE__) == 43) || (__VA_ARGS__), \
int \
>::type = 0 \
/**/因此,简而言之,模板定义如下:
template<typename I, typename O,
CONCEPT_REQUIRES_(InputIterator<I>() &&
WeaklyIncrementable<O>())>
void fun_signature() {}翻译为:
template<typename I, typename O,
int a_unique_name = 42,
typename std::enable_if
<false || (InputIterator<I>() &&
WeaklyIncrementable<O>()), int>::type = 0
>
void fun_signature() {}我想知道为什么那个宏是这样实现的。为什么需要这个整数,为什么它需要一个false || cond而不仅仅是一个cond模板参数?
发布于 2017-08-25 18:48:21
模板定义就像..。翻译成..。
关。它实际上翻译为:
template<typename I, typename O,
int a_unique_name = 42,
typename std::enable_if
<a_unique_name == 43 || (InputIterator<I>() &&
WeaklyIncrementable<O>()), int>::type = 0
>
void fun_signature() {}唯一命名的int是为了确保enable_if的条件依赖于模板参数,以避免在模板定义时而不是在实例化时检查条件,从而使SFINAE能够发生。考虑一下这个类的定义:
template<class T>
struct S {
template<class U, CONCEPT_REQUIRES_(ranges::Integral<T>())>
void f(U);
};如果没有注入唯一的-int,这个定义将降低到:
template<class T>
struct S {
template<class U, std::enable_if_t<ranges::Integral<T>()>>
void f(U);
};而且由于ranges::Integral<T>()不依赖于这个函数模板的参数,编译器将诊断std::enable_if_t<ranges::Integral<T>()> (它降低到typename std::enable_if<ranges::Integral<T>()>::type )是不正确的,因为std::enable_if<false>不包含名为type的成员。使用注入的唯一-int,类定义降低到:
template<class T>
struct S {
template<class U, int some_unique_name = 42,
std::enable_if_t<some_unique_name == 43 || ranges::Integral<T>()>>
void f(U);
};现在,编译器无法在模板定义时执行对enable_if_t的任何分析,因为some_unique_name是一个模板参数,用户可以将其指定为43。
https://stackoverflow.com/questions/45887392
复制相似问题