g ++ 4.9.2 регрессия на проходной ссылке на ‘this’

Это минимизированная часть указателя на код реализации:

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 ++, которая устраняет обратную совместимость?

3

Решение

Мы можем сделать более простой пример, который не компилируется ни в 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&&оба компилятора принимают код.

3

Другие решения

Это не скомпилировалось для меня с gcc-4.6, поэтому кажется, что в gcc-4.8 произошла регрессия. Кажется, что вы хотите, это взять A1 по универсальной ссылке, то есть: PImpl(A1 && a1), Это компилирует для меня и gcc-4.6, gcc-4.8 и gcc-4.9.

1

По вопросам рекламы [email protected]