这是实现代码指针的最小化部分:
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 ++标准功能是否会消除向后兼容性?
答案 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编译。