C++ 模板参数在gcc6中的部分专门化中不可推断,用于在gcc5中工作的情况
此代码导致gcc6出错(但在GCC4.8、5.2和clang 3.6中工作正常): 看 我已在此处向gcc提交了一份错误报告: 然而,它被标记为无效(我错误地认为)。在C++ 模板参数在gcc6中的部分专门化中不可推断,用于在gcc5中工作的情况,c++,templates,gcc,language-lawyer,C++,Templates,Gcc,Language Lawyer,此代码导致gcc6出错(但在GCC4.8、5.2和clang 3.6中工作正常): 看 我已在此处向gcc提交了一份错误报告: 然而,它被标记为无效(我错误地认为)。在谓词内部使用的外部在该点上是一个具体类型,因此它不是一个非推断上下文 P>标准中有什么可以防止这是有效的C++代码吗?< /强> < p>我怀疑这是GCC 6中的一个bug,并且在CLAN 3.9中有一个错误警告(警告是奇怪的),因为警告意味着部分的专业化不会被选择,但是如果没有选择,静态断言会触发。 来自[温度等级规格匹配
谓词
内部使用的外部
在该点上是一个具体类型,因此它不是一个非推断上下文
<> P><强>标准中有什么可以防止这是有效的C++代码吗?< /强> < p>我怀疑这是GCC 6中的一个bug,并且在CLAN 3.9中有一个错误警告(警告是奇怪的),因为警告意味着部分的专业化不会被选择,但是如果没有选择,静态断言会触发。
来自[温度等级规格匹配]: 如果 部分专门化可以从实际的模板参数列表中推导出来 我们能从
outer::inner
推断typename outer::template inner
中的U
吗
从[临时扣除类型]:
如果模板参数仅在非默认情况下使用
上下文,并且未显式指定,模板参数推断失败
非推断上下文为:-使用限定id指定的类型的嵌套名称说明符。
-[……] 但是这里指定的嵌套名称是
typename outer
,它不包含我们试图推断的类型。其他未推导的上下文都不适用。因此,演绎应该在这里成功
考虑以下等效情况:
#include <utility>
template <class >
struct outer
{
template <class U> struct inner {};
};
template <class T>
struct bar {
template <class U> std::false_type foo(U const&);
template <class U> std::true_type foo(typename outer<T>::template inner<U> const&);
};
int main() {
static_assert(decltype(bar<int>{}.foo(outer<int>::inner<double>{}))::value, "!");
}
#包括
模板
结构外部
{
模板结构内部{};
};
模板
结构条{
模板std::false_type foo(U const&);
模板std::true_type foo(typename外部::模板内部常量&);
};
int main(){
静态_断言(decltype(bar{}.foo(outer::inner{}))::value,“!”;
}
GCC6.0和Clang3.9都在没有警告的情况下编译了这段代码——但这与原始示例中的部分专门化中发生的情况是相同的
main.cpp:22:9: error: template parameters not deducible in partial specialization:
struct predicate<typename outer<T>::template inner<U>> : std::true_type
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:22:9: note: 'U'
^~~~~~~~~~~~~
g++ -std=c++1y -c main.cpp
#include <utility>
template <class >
struct outer
{
template <class U> struct inner {};
};
template <class T>
struct bar {
template <class U> std::false_type foo(U const&);
template <class U> std::true_type foo(typename outer<T>::template inner<U> const&);
};
int main() {
static_assert(decltype(bar<int>{}.foo(outer<int>::inner<double>{}))::value, "!");
}