со следующим кодом (своя версия моего исходного кода)
#include <iostream>
#include <cmath>
template <typename> class A; // edit 1 following Mark & Matthieu
template <typename X> class A {
X a;
template <typename> friend class A; // edit 1 following Mark & Matthieu
public:
A(X x) : a(x) {}
X get() const { return a; } // edit 2 to avoid using A<Y>::a
template <typename Y>
auto diff(A<Y> const& y) const
-> decltype(a - y.a) // original code causing error with gcc
-> typename std::common_type<X, Y>::type // alternative following Rook
-> decltype(this->get() - // edit 3 not using A<X>::a
y.get()) // edit 2 not using A<Y>::a
{ return a - y.get(); }
};
template <typename X, typename Y>
inline auto dist(A<X> const& x, A<Y> const& y) -> decltype(std::abs(x.diff(y)))
{ return std::abs(x.diff(y)); }
int main()
{
A<double> x(2.0), y(4.5);
std::cout << " dist(x,y)=" << dist(x,y) << '\n'; // <-- error here
}
Я получаю следующую ошибку с gcc 4.7.0:
test.cc: В функции
decltype (std::abs(x.diff(y))) dist(const A<X>&, const A<Y>&)
[сX = double; Y = double; decltype (std::abs(x.diff(y))) = double
]:test.cc:5:5: ошибка:
double A<double>::a
является закрытойвыделенная строка: ошибка: в этом контексте
Это сообщение об ошибке явно не очень полезно. Есть ли ошибка в моем коде? Или это проблема с компилятором?
EDIT1: объявление друга не помогло.
EDIT2: избегать использования A<Y>::a
тоже не помогло.
EDIT3: вместе с EDIT2 наконец исправлена проблема. decltype()
в определении dist()
требует decltype()
для A<X>::diff()
, который, в свою очередь, использовал A<X>::a
, который является приватным в первом контексте.
EDTI4: предложение ладьи с использованием typename std::common_type<X,Y>::type
также работает!
EDIT5: но см. Джонатан Вакели на этот вопрос