在C ++ 11中使用decltype()时出错(在gcc 4.7.0中创建不透明的错误消息) [英] Error with using decltype() in C++11 (creating opaque error message in gcc 4.7.0)

查看:180
本文介绍了在C ++ 11中使用decltype()时出错(在gcc 4.7.0中创建不透明的错误消息)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用以下代码(原始代码的冻结版本)

  #include< iostream> 
#include< cmath>

template< typename> A类; // edit 1 following Mark& Matthieu
template< typename X> A类{
X a;
template< typename>朋友A类; // edit 1 following Mark& Matthieu
public:
A(X x):a(x){}
X get()const {return a; } //编辑2以避免使用A< Y> :: a
模板< typename Y>
auto diff(A< Y> const& y)const
- > decltype(a - y.a)//原始代码导致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不使用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) '\\\
'; //< - error here
}



我收到以下错误gcc 4.7 .0:


test.cc:在函数 decltype(std :: abs(x.diff(y) ))dist(const A X& const A Y&) [with X = double; Y =双; decltype(std :: abs(x.diff(y)))= double ]':



test.cc:5:5:错误: double A< double> :: a 是私人的



p>

这个错误消息显然不是很有帮助。我的代码中是否有错误?或者这是编译器的问题?



EDIT1 :朋友声明没有帮助。



EDIT2 :避免使用 A< Y> :: a 没有帮助。



EDIT3 :与 EDIT2 一起最终修复问题 dist()定义中的 decltype()需要 decltype() for A< X> :: diff(),其依次使用 A< X> :: a EDTI4 :Rook建议使用 typename std :: common_type< X,Y> :: type 也有效!



EDIT5 :但是看Jonathan Wakely的回答< a href =http://stackoverflow.com/questions/11055350/what-is-better-to-use-for-automatic-return-types-decltype-or-stdcommon-type#comment14465455_11055350>此问题

解决方案

TL; DR: Gcc 似乎有一个错误,其中模板成员函数的尾随返回类型不被视为类的作用域内。



当实例化模板成员函数 auto diff(A< Y> const& y)const - >时,该错误导致gcc失败。因为 a 是私有的,而gcc认为私人成员在这里不可访问。






代码使用clang和VC ++构建,我没有看到任何试图访问 A< double> :: a outside A< double> ,所以它看起来像一个gcc bug给我。



提到 A< X> A< Y> 是不同的类,但是这里不是这样, A< double> 。我相信这意味着在这种情况下不需要友谊,虽然在一般情况下工作 A 需要是与A的其他专业化的朋友。 p>

具体来说,中的 a 是一个依赖名称,因此不能被查找,直到 A< Y> 是已知的。在那时查找完成,测试可访问性,并且应当发现 A 确实可以访问 A



下面是我在clang(svn-3.2)和VC ++ 11中编译的代码(因为我使用clang在Windows上我不能 #include< iostream>

  #include< cmath> 

template< typename X> A类{
X a;
public:
A(X x):a(x){}
template< typename Y>
auto diff(A< Y> const& y)const - > decltype(a-y.a)
{return a-y.a; }
};

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);
return(int)dist(x,y);
}

此代码会导致在gcc 4.5上构建错误 类似于你所描述的。



更换

 自动比较(A< Y>常数& y )const  - > decltype(ay.a)

  auto diff(A< Y> const& y)const  - typename std :: common_type< X,Y> :: type 

导致代码在gcc 4.5 上工作。



这向我显示一个错误,其中gcc未能将尾部返回类型视为类的作用域。 有些测试显示,尾随返回类型必须在模板函数上才能触发错误。


with the following code (a boiled-down version of my original code)

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

I get the following error with gcc 4.7.0:

test.cc: In function decltype (std::abs(x.diff(y))) dist(const A<X>&, const A<Y>&) [with X = double; Y = double; decltype (std::abs(x.diff(y))) = double]’:

test.cc:5:5: error: double A<double>::a is private

highlighted line: error: within this context

This error message is obviously not very helpful. Is there an error in my code? Or is this a problem with the compiler?

EDIT1: the friend declaration didn't help.

EDIT2: avoiding using A<Y>::a didn't help either.

EDIT3: together with EDIT2 finally fixed the problem. The decltype() in the definition of dist() requires the decltype() for A<X>::diff(), which in turn used A<X>::a, which is private in the first context.

EDTI4: Rook's suggestion of using typename std::common_type<X,Y>::type also works!

EDIT5: but see Jonathan Wakely's answer to this question

解决方案

TL;DR: Gcc appears to have a bug where trailing return types on template member functions are not treated as within the class's scope.

This bug causes gcc to fail when instantiating the template member function auto diff(A<Y> const&y) const -> decltype(a-y.a) because a is private and gcc thinks private members are inaccessible here.


The code builds fine with clang and VC++, and I don't see anything trying to access A<double>::a outside A<double>, so it looks like a gcc bug to me.

Others have mentioned that A<X> and A<Y> are different classes, but that's not the case here, both are A<double>. I believe that means that friendship is not necessary in this case, although to work in the general case A<X> does need to be friends with other specializations of A.

Specifically, a in y.a is a dependent name so it cannot be looked up until A<Y> is known. At that point lookup is done, the accessibility is tested and it should be found that A<double> does have access to A<double>::a.

Here's the exact code I compiled in both clang (svn-3.2) and VC++11 (Since I'm using clang on Windows I can't #include <iostream>)

#include <cmath>

template<typename X> class A {
  X a;
public:
  A(X x) : a(x) {}
  template<typename Y>
  auto diff(A<Y> const&y) const -> decltype(a-y.a)
  { return a-y.a; }
};

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);
  return (int) dist(x,y);
}

This code results in build errors on gcc 4.5 similar to what you describe.

Replacing

auto diff(A<Y> const&y) const -> decltype(a-y.a)

with

auto diff(A<Y> const&y) const -> typename std::common_type<X,Y>::type

causes the code to work on gcc 4.5.

This indicates to me a bug where gcc is failing to treat trailing return types as inside the class's scope. Some testing reveals that the trailing return type must be on a template function to trigger the bug.

这篇关于在C ++ 11中使用decltype()时出错(在gcc 4.7.0中创建不透明的错误消息)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆