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

问题描述 投票:0回答:2

如何使用 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;
}

预期/期望的输出是:

Value of a = 3
Value of a = 5

但是现在,假设我希望编译器推断出

get()
中的 const 和非常量
A<T>
函数返回的类型,并且我想确保这两个调用都将 references 返回到
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_;
  }
};

但是编译失败。 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

这样做的动机在于我提炼的示例代码,但源于尝试减少模板采用的参数数量,当这些参数中的一个(或多个)仅用于指定编译器应该返回的类型时(我认为) 能够自行推论。注意:在现实世界中,

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_;
  }
};

任何有助于理解我所缺少的东西的人将不胜感激。

详情:

Centos 6.5
gcc (GCC) 4.7.2 20121015 (Red Hat 4.7.2-5)
c++ templates c++11 auto decltype
2个回答
18
投票

提一下,您实际上不必使用

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;
}

7
投票

a_
包裹在尾随返回类型的一对额外括号中,以获得表达式
a_
的类型,而不是变量的声明类型
a_
Live at 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_;
}

或者如果 C++1y 可用

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

// 2. Return non-const reference to a_
auto& get()
{
  return a_;
}
© www.soinside.com 2019 - 2024. All rights reserved.