公用“使用” = decltype(<private>)

时间:2018-10-19 01:49:54

标签: c++ c++11 templates language-lawyer decltype

在以下(最小化)代码中,我有一个公共using声明,该声明引用了decltype(something_private)using Foo = decltype(something_private<T>)

在Clang而非GCC上,由于它是私有的,因此无法编译。

问题:

  1. 如果我不想公开func<T>(),那是一个优雅的解决方案。
  2. 在C ++标准(C ++ 11)中,备份Clang在这里正确吗?

以下代码在Clang(3.9-7.0)上失败,并显示以下错误代码,但在GCC(4.8.4-8.2)上构建:

class A {
private:
    template <class T>
    static auto func() -> T; // The actual return type is much
       // more complicated, so `using Foo = T` would not work.

public:
    template <class T>
    using Foo = decltype(func<T>());
};

int main(int, char**) {
    A::Foo<int> y;
    return y;
}

Clang 7.0输出:

<source>:10:24: error: 'func' is a private member of 'A'
  using Foo = decltype(func<T>());
                       ^~~~~~~

<source>:14:7: note: in instantiation of template type alias 'Foo' requested here
   A::Foo<int> y;
          ^

<source>:6:15: note: declared private here
  static auto func() -> T;
              ^

1 error generated.
Compiler returned: 1

https://godbolt.org/z/zD4Hk5

1 个答案:

答案 0 :(得分:9)

我没有考虑引用标准,但是为您提供了一种解决方法。因为这样做有效,所以让我认为clang仅存在一个错误。当函数直接位于A中时,它将类型别名视为在调用方的上下文中,但是将函数移入结构即可解决。嗯我最近做了很多g ++ / clang的移植,虽然我没有专门碰到这一点,但它闻到了我遇到的一些东西。

class A {
private:
  struct X {
    template <class T>
    static auto func() -> T;
  };

public:
  template <class T>
  using Foo = decltype(X::func<T>());
};

void bar() {
   A::Foo<int> y;
}

https://godbolt.org/z/ozIS-r

更新:添加了引文。

我认为这直接回答了您的问题,而这里的叮当声是错误的。

  

N4778(我找到的最新版本),10.8 / p4(第259页)... [注意:由于访问控制适用于名称,因此,如果将访问控制应用于typedef名称,则只有typedef名称本身的可访问性是考虑过的。不考虑由typedef引用的实体的可访问性。