使用auto和decltype从模板化类中的函数返回引用

dun*_*can 13 c++ templates decltype auto c++11

如何使用auto/decltype强制模板化类中的函数返回对成员变量的引用?

这是我正在尝试做的一个简单的例子.假设您有一个模板化的类,它将某些内容存储在私有成员变量中,a_如下所示:

#include <iostream>

template <typename T>
class A
{
private:
  T a_;

public:
  A(T a) : a_(a) {}

  // 1. Return const reference to a_
  const T & get() const { return a_; }

  // 2. Return non-const reference to a_
  T & get() { return a_; }
};

int main(int argc, char *argv[])
{
  A<int> a(3);

  const auto & a1 = a.get(); // 1. Return const reference to a_
  //a1 = 4;  // Shouldn't compile
  std::cout << "Value of a = " << a.get() << std::endl;

  auto & a2 = a.get(); // 2. Return non-const reference to a_
  a2 = 5;
  std::cout << "Value of a = " << a.get() << std::endl;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

预期/期望的输出是:

Value of a = 3
Value of a = 5
Run Code Online (Sandbox Code Playgroud)

但现在,假设我希望编译器来推断由常量和非const返回类型get()的功能A<T>,我想,以确保这两个调用返回引用a_.

我最好的猜测是:

template <typename T>
class A
{
private:
  T a_;

public:
  A(T a) : a_(a) {}

  // 1. Return const reference to a_
  const auto get() const -> std::add_lvalue_reference<const decltype(a_)>::type
  {
    return a_;
  }

  // 2. Return non-const reference to a_
  auto get() -> std::add_lvalue_reference<decltype(a_)>::type
  {
    return a_;
  }
};
Run Code Online (Sandbox Code Playgroud)

但是无法编译.GCC给出的第一个错误是:

decltype.cpp:11:29: error: expected type-specifier
decltype.cpp:11:26: error: expected ‘;’ at end of member declaration
decltype.cpp:11:29: error: ‘add_lvalue_reference’ in namespace ‘std’ does not name a type
Run Code Online (Sandbox Code Playgroud)

这样做的动机就在于我的精简示例代码,但是源于尝试减少模板所使用的参数数量,这些参数中的一个(或多个)仅用于指定编译器应该返回的返回类型(我认为)能够自己演绎.注意:在现实世界中,返回类型get()不是a_,但是f(a_)我知道编译器可以推导的某些函数的返回类型.因此,在这个例子中我需要auto/decltype.

令我困惑的是,编译器可以使用非模板类中几乎相同的代码正确推导出返回类型:

class A
{
private:
  int a_;

public:
  A(int a) : a_(a) {}

  // 1. Return const reference to a_
  const auto get() const -> std::add_lvalue_reference<const decltype(a_)>::type
  {
    return a_;
  }

  // 2. Return non-const reference to a_
  auto get() -> std::add_lvalue_reference<decltype(a_)>::type
  {
    return a_;
  }
};
Run Code Online (Sandbox Code Playgroud)

任何帮助,以了解我所缺少的将不胜感激.

细节:

Centos 6.5
gcc (GCC) 4.7.2 20121015 (Red Hat 4.7.2-5)
Run Code Online (Sandbox Code Playgroud)

Sti*_*org 16

仅举这一点,你实际上不必std::add_lvalue_reference用来获得你想要的行为.这也很有效,在我的书中更具可读性.

template <typename T>
class A {
    private:
        T a_; 

    public:
        A(T a) : a_(a) {}

        const auto get() const -> const decltype(a_) & {
            return a_; 
        }

        auto get() -> decltype(a_) & {
            return a_; 
        }
};

int main() {
    A<int> a(1);
    cout << a.get() << endl;
    a.get() = 2;
    cout << a.get() << endl;
}
Run Code Online (Sandbox Code Playgroud)


Cas*_*sey 5

a_在尾随返回类型一对额外的括号来获得表达的类型a_,而不是声明的类型变量a_在Coliru直播):

// 1. Return const reference to a_
auto get() const -> decltype((a_))
{
  return a_;
}

// 2. Return non-const reference to a_
auto get() -> decltype((a_))
{
  return a_;
}
Run Code Online (Sandbox Code Playgroud)

或者如果C++1y 可用

// 1. Return const reference to a_
auto& get() const
{
  return a_;
}

// 2. Return non-const reference to a_
auto& get()
{
  return a_;
}
Run Code Online (Sandbox Code Playgroud)

  • `auto&amp;` 可以很好地推断出对 const 类型的引用。在这种情况下,“const auto&amp;”不会更正确,只会更明确。 (3认同)
  • 不应该 `auto&amp; get() const { return a_; }` 是 `const auto&amp; get() const { return a_; }` 如果你想返回一个常量引用?函数名后面的 const a 表示可以在其所属的常量对象上调用该成员函数。 (2认同)