考虑 this代码:
#include <type_traits>
template < int > struct II { };
template < const int& > struct RR { };
template < template <auto> typename Class, typename Type > struct Check : std::false_type { };
template < template <auto> typename Class, auto NonTypes > struct Check<Class,Class<NonTypes>> : std::true_type { };
constexpr int TEN = 10;
constexpr const int& REF = TEN;
static_assert(Check<II,II<TEN>>::value); // passes
static_assert(Check<RR,RR<REF>>::value); // FAILS!?
我正在使用 gcc-7.0.1 和 here是活生生的例子。问题是这是编译器错误还是我做错了什么?
最佳答案
让我们稍微简化一下示例:
template <template <auto> class C, auto N>
void foo(C<N> ) { }
int main() {
foo(II<TEN>{} ); // ok
foo(RR<REF>{} ); // error
}
问题是正常的auto
扣除规则适用于N
,在 REF
中推导出来案例类型 int
.非类型模板参数类型不匹配 - int const&
- 和参数 - int
, 所以它的格式不正确。
如果我们将示例翻转为 auto const& N
(或 auto&& N
),那么它将是 II<TEN>
出于同样的原因,调用将是格式错误的——我们现在得到一个引用类型的模板参数,但该参数是一个非引用类型。
您无法使用当今语言中的一个函数来处理这两种情况。你需要两个:
template <template <auto> class C, auto N> void foo(C<N> ) { } // #1
template <template <auto&&> class C, auto&& N> void foo(C<N> ) { } // #2
int main() {
foo(II<TEN>{} ); // ok: calls #1
foo(RR<REF>{} ); // ok: calls #2
}
与您的原始示例类似:您需要一种针对值的特化和一种针对引用的特化。 C
的模板-模板非类型参数中的引用可能没有必要。
关于c++ - gcc 中带有 const& 模板参数的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42133141/