Это минимизированная часть указателя на код реализации:
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>&'
Но это можно исправить небольшим взломом. Если я пройду&*этот‘ вместо ‘этот«Затем он приведет к компилируемому состоянию.
Это регрессия G ++ или новая функция стандартов C ++, которая устраняет обратную совместимость?
Мы можем сделать более простой пример, который не компилируется ни в g ++ 4.9, ни в clang:
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 чья ценность
адрес объекта, для которого вызывается функция.
Вы не можете взять lvalue ссылку на prvalue, отсюда и ошибка — которая в этом случае объясняет gcc лучше, чем clang:
ошибка: неверная инициализация неконстантной ссылки типа
A*&
от значения типаA*
Если мы переписать call
либо взять const T&
или T&&
оба компилятора принимают код.
Это не скомпилировалось для меня с gcc-4.6, поэтому кажется, что в gcc-4.8 произошла регрессия. Кажется, что вы хотите, это взять A1
по универсальной ссылке, то есть: PImpl(A1 && a1)
, Это компилирует для меня и gcc-4.6, gcc-4.8 и gcc-4.9.