g ++ 4.9.2对'this'的传递引用的回归

时间:2015-02-05 14:23:39

标签: c++ gcc4.9 g++4.9

这是实现代码指针的最小化部分:

template<typename T>
class PImpl {
private:
  T* m;
public:

  template<typename A1> 
  PImpl(A1& a1) : m(new T(a1)) {
  }
};

struct A{
    struct AImpl;
    PImpl<AImpl> me;
    A();
};

struct A::AImpl{
    const A* ppub;
    AImpl(const A* ppub)
    :ppub(ppub){}
};
A::A():me(this){}

A a;
int main (int, char**){
    return 0;
}

它可以在G ++ 4.8和之前编译,也适用。但是G ++ 4.9.2编译器引发了以下错误:

prog.cpp: In constructor 'A::A()':
prog.cpp:24:15: error: no matching function for call to 'PImpl<A::AImpl>::PImpl(A*)'
 A::A():me(this){}
               ^
prog.cpp:24:15: note: candidates are:
prog.cpp:9:5: note: PImpl<T>::PImpl(A1&) [with A1 = A*; T = A::AImpl]
   > PImpl(A1& a1) : m(new T(a1)) {
     ^
prog.cpp:9:5: note:   no known conversion for argument 1 from 'A*' to 'A*&'
prog.cpp:2:7: note: PImpl<A::AImpl>::PImpl(const PImpl<A::AImpl>&)
 class PImpl {
       ^
prog.cpp:2:7: note:   no known conversion for argument 1 from 'A*' to 'const PImpl<A::AImpl>&'

但它可以通过小黑客来解决。如果我通过&#39; &amp; *这个&#39;而不是&#39; 这个&#39;然后它带来可编辑的状态。

G ++回归或新的C ++标准功能是否会消除向后兼容性?

2 个答案:

答案 0 :(得分:3)

我们可以做一个简单的例子,既不编译g ++ 4.9也不编译:

template <typename T>
void call(T& ) {  }

struct A { 
    void foo() { call(this); }
};

int main()
{
    A().foo();
}

那是因为this来自标准,[class.this](§9.3.2):

  

在非静态(9.3)成员函数的主体中,关键字this prvalue表达式,其值   是调用该函数的对象的地址。

你不能对一个prvalue进行左值引用,因此错误 - 在这种情况下gcc比clang解释得更好:

  

错误:从A*&类型的右值

中初始化A*类型的非const引用无效

如果我们重写call以获取const T&T&&,则两个编译器都会接受该代码。

答案 1 :(得分:1)

这对我来说并不是用gcc-4.6编译的,所以似乎gcc-4.8是回归发生的地方。您希望通过通用引用获取A1,即:PImpl(A1 && a1)。这用gcc-4.6,gcc-4.8和gcc-4.9编译。