首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板参数在gcc6中的部分专门化中不可还原,对于过去在gcc5中工作的情况

模板参数在gcc6中的部分专门化中不可还原,对于过去在gcc5中工作的情况
EN

Stack Overflow用户
提问于 2016-03-08 19:04:05
回答 1查看 3.3K关注 0票数 5

此代码导致gcc6中的一个错误(但是在gcc 4.8、5.2和clang3.6中工作得很好):

代码语言:javascript
复制
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!"
);

错误是:

代码语言:javascript
复制
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'
 ^~~~~~~~~~~~~

总司令是:

代码语言:javascript
复制
g++ -std=c++1y -c main.cpp

这里的输出

我在这里向gcc提交了一份错误报告:bug.cgi?id=70141

然而,它被标记为无效(我认为是错误的)。在这一点上,在outer<T>中使用的predicate是一个具体的类型,所以它不是一个非推导的上下文。

标准中有什么东西可以防止这是有效的c++代码吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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>,它不包含我们试图推断的类型。其他未推导的上下文都不适用。因此,演绎应该在这里成功。

考虑以下类似情况:

代码语言:javascript
复制
#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都在没有警告的情况下编译了这段代码--但这与原始示例中的部分专门化一样。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35875829

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档