此代码导致gcc6中的一个错误(但是在gcc 4.8、5.2和clang3.6中工作得很好):
template <typename T>
struct outer
{
template <typename U>
struct inner
{
};
};
template <typename T>
struct is_inner_for
{
template <typename Whatever>
struct predicate
{
static constexpr bool value = false;
};
template <typename U>
struct predicate<typename outer<T>::template inner<U>>
{
static constexpr bool value = true;
};
};
static_assert(
is_inner_for<int>::template predicate<
outer<int>::inner<double>
>::value,
"Yay!"
);错误是:
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见这里的输出。
我在这里向gcc提交了一份错误报告:bug.cgi?id=70141
然而,它被标记为无效(我认为是错误的)。在这一点上,在outer<T>中使用的predicate是一个具体的类型,所以它不是一个非推导的上下文。
标准中有什么东西可以防止这是有效的c++代码吗?
发布于 2016-03-08 20:33:55
我怀疑这是gcc 6.0中的一个bug,在clang 3.9中是一个错误的警告(警告很奇怪--因为警告意味着不选择部分专门化,但是如果不选择它,静态断言就会触发)。
来自temp.class.spec.match
如果可以从实际模板参数列表中推导出部分专门化的模板参数,则部分专门化与给定的实际模板参数列表匹配。
我们能从U中推断出typename outer<T>::template inner<U>中的outer<int>::inner<double>吗?
来自temp.deduct.type
如果模板参数仅在非推导上下文中使用,且未显式指定,则模板参数演绎失败。未推导的上下文如下: -使用限定-id指定的类型的嵌套名称说明符。 -.
但是这里指定的嵌套名称是typename outer<T>,它不包含我们试图推断的类型。其他未推导的上下文都不适用。因此,演绎应该在这里成功。
考虑以下类似情况:
#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, "!");
}gcc 6.0和clang3.9都在没有警告的情况下编译了这段代码--但这与原始示例中的部分专门化一样。
https://stackoverflow.com/questions/35875829
复制相似问题