簡體   English   中英

使用auto和decltype從模板化類中的函數返回引用

[英]Using auto and decltype to return reference from function in templated class

如何強制模板化類中的函數使用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

但是現在,假設我想讓編譯器推斷A<T> const和non-const get()函數返回的類型,並且我想確保兩個調用都返回對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_)的返回類型,我知道編譯器可以推導該函數。 因此,在此示例中,我需要自動/ 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)

只需提一下,您實際上不必使用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;
}

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

或者如果C ++ 1y可用

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM