【发布时间】:2012-06-15 14:38:22
【问题描述】:
使用以下代码(我的原始代码的简化版本)
#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>&)[withX = 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一起终于解决了问题。 dist() 定义中的 decltype() 需要 decltype() 用于 A<X>::diff(),而 A<X>::diff() 又使用 A<X>::a,在第一个上下文中是私有的。
EDTI4:Rook 建议使用typename std::common_type<X,Y>::type 也有效!
EDIT5:但请参阅 Jonathan Wakely 对this question的回答
【问题讨论】:
-
使用 gcc-4.3 您的代码也无法编译。有关返回的错误,请参阅 this link。
-
@PenguinCoder:gcc-4.3 不支持 C++11(又名 C++0x)。这个问题是关于 gcc-4.7 的。
-
@JohnDibling:我不会关心模板代码中的 MSVC,它没有实现两阶段查找,因此无法检查许多事故。然而,Clang 拒绝它的事实是一个红鲱鱼。
-
还有一个问题要问大家...
std::common_type<X, Y>会更适合diff()吗? 看起来应该是这样,但我无法在 gcc 4.4 或 vs2010 中编译它... -
@Rook:不错的选择!我认为可以安全地假设这是一个 gcc 错误,因为没有理由稍后应该允许在
decltype中拒绝的表达式出现在正文中。不一致。