Как я могу принудить функцию в templated классе возвращать ссылку на переменную-член, используя 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
Но теперь предположим, что я хочу, чтобы компилятор выводил тип, возвращаемый функциями const и non-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_;
}
};
но это не скомпилируется. Первая ошибка, заданная 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)