【问题标题】:Using this and attributes in member function trailing return types?在成员函数尾随返回类型中使用 this 和属性?
【发布时间】:2012-01-26 13:03:27
【问题描述】:

在我给出的这个answer 中,使用this 和在尾随返回类型中的_arg 类的属性作为decltype 表达式的一部分是有意义的。可以不用,但不方便。

clang 3.0(见下文)和gcc 4.5.2 都没有接受它。

#include <iostream>

class MyClass {
public:
  MyClass(int i): _arg(i) {}

  template <typename F>
  auto apply(F& f) -> decltype(f(_arg)) {
    return f(_arg);
  }

  template <typename F>
  auto apply(F& f) -> decltype(f(*this, _arg)) {
    return f(*this, _arg);
  }

private:
  int _arg;
};

struct Id {
  template <typename V>
  V operator()(V v) const { return v; }
};

struct ComplexId {
  template <typename C, typename V>
  V operator()(C const&, V v) { return v + 1; }
};

int main() {
  Id id; ComplexId complex;

  MyClass c(0);

  std::cout << c.apply(id) << " " << c.apply(complex) << "\n";
}

clang 3.0 说:

$ clang++ -std=c++11 -Weverything test.cpp
test.cpp:8:38: error: use of undeclared identifier '_arg'
      auto apply(F& f) -> decltype(f(_arg)) {
                                     ^
test.cpp:8:45: error: type name requires a specifier or qualifier
      auto apply(F& f) -> decltype(f(_arg)) {
                                            ^
test.cpp:8:45: error: C++ requires a type specifier for all declarations
      auto apply(F& f) -> decltype(f(_arg)) {
                          ~~~~~~~~          ^
test.cpp:8:7: error: 'auto' return without trailing return type
      auto apply(F& f) -> decltype(f(_arg)) {
      ^
test.cpp:13:39: error: invalid use of 'this' outside of a nonstatic member function
      auto apply(F& f) -> decltype(f(*this, _arg)) {
                                      ^
test.cpp:13:52: error: type name requires a specifier or qualifier
      auto apply(F& f) -> decltype(f(*this, _arg)) {
                                                   ^
test.cpp:13:52: error: C++ requires a type specifier for all declarations
      auto apply(F& f) -> decltype(f(*this, _arg)) {
                          ~~~~~~~~                 ^
test.cpp:13:7: error: 'auto' return without trailing return type
      auto apply(F& f) -> decltype(f(*this, _arg)) {
      ^
8 errors generated.

嗯...不太好。

但是,在大多数编译器中,对 C++11 的支持充其量只是 hacky,我找不到标准 (n3290) 中提到的具体限制。

在 cmets 中,Xeo 表示这可能是标准中的一个缺陷......

那么,这是否允许?

奖励:clang / gcc 的最新版本是否支持此功能?

【问题讨论】:

  • Clang 3.1 HEAD 发出同样的错误。
  • 顺便说一句,我刚刚找到this interesting, similar question。此外,根据@Johannes 建议预先声明成员,我只会在尾随返回类型中收到关于 this 的错误,而不再使用 Clang 3.1 HEAD 收到关于 _arg 的错误。
  • @Xeo:是的,我见过这个问题,但它更多的是关于 const-ness 而不是this。我没有测试过 Johannes 的建议,很高兴知道它减少了编译器产生的错误数量。

标签: c++ c++11 trailing-return-type


【解决方案1】:

我记错了。它是a defect at some point,但最终是resolved and voted into the FDIS

§5.1.1 [expr.prim.general]

如果声明声明了类 X 的成员函数或成员函数模板,则表达式 this 是“指向 cv-qualifier-seq X 的指针”类型的纯右值在可选的 cv-qualifer-seqfunction-definitionmember-declaratordeclarator的结尾之间>.

因此,Clang 和 GCC 还没有正确实现它。

struct X{
  // 'this' exists between the | markers
  void f() const volatile | {
  } |
  auto g() const volatile | -> void {
  } |
};

【讨论】:

    【解决方案2】:

    您的代码无效的 C++11,因为该类在成员函数的返回类型中不被认为是完整的。您只能访问先前已声明的成员。像这样

    class MyClass {
    private:
      int _arg;
    
    public:
      MyClass(int i): _arg(i) {}
    
      template <typename F>
      auto apply(F& f) -> decltype(f(_arg)) {
        return f(_arg);
      }
    
      template <typename F>
      auto apply(F& f) -> decltype(f(*this, _arg)) {
        return f(*this, _arg);
      }
    };
    

    模数,是的,使用 this 在 C++11 的尾随返回类型中是有效的。

    【讨论】:

    • 啊,这很有趣。我没有考虑过,但这是有道理的,因为如果我没记错的话,这同样适用于类型(即,即使在类中也需要在使用之前声明它们)。
    • 没有内部成员函数体,该类被认为是完整的。所以即使是稍后声明的成员类型也是可见的。
    • 我特别想this:struct A { type foo(); typedef int type; };。总是把我当作 old-style 解析:x
    • 但这对所有成员都是一样的。 struct { decltype(foo) bar(); int foo; }; 因同样原因无效。
    • 是的,而且是有道理的,因为我们还在函数的声明中,但是我花了一段时间才意识到。
    【解决方案3】:

    我不知道你写的是否合法,但是还有一些其他的方法可以实现你想要的:

      template <typename F>
      auto apply(F& f) -> decltype(f(*(MyClass*)0, (int)0)) {
        return f(*this, _arg);
      }
    

    或者:

      template <typename F>
      typename std::result_of<F(MyClass,int)>::type apply(F& f) {
        return f(*this, _arg);
      }
    

    【讨论】:

    • 在我链接到的答案中,给出了一个更详细的表格。注意std::declval&lt;T&gt; 的存在允许在未评估的上下文中,空指针技巧不是必需的:)
    猜你喜欢
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多