2015-02-05 5 views
3

Это уменьшенная часть Указателя на код реализации:г ++ 4.9.2 регрессии по ссылке перейти к «это»

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

ответ

1

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

+0

Он составлен на gcc-4.3.2: http://ideone.com/nKcI6m – slonma

3

Мы можем сделать более простой пример, который компилирует на ни г ++ 4.9, ни лязг:

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

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

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

Это потому, что this есть, от стандарта, [class.this] (§9.3.2):

In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called.

Вы не можете принять Lvalue ссылки на prvalue, отсюда и ошибку - что НКУ объясняет лучше, чем звон в этом случае:

error: invalid initialization of non-const reference of type A*& from an rvalue of type A*

Если мы перепишем call либо взять const T&, либо T&&, оба компилятора согласны с кодом.

+0

Почему «& * this' работает? – 0x499602D2

+0

@ 0x499602D2 Потому что '* this' является lvalue. – Barry

+0

Но '& x' возвращает значение prvalue. – 0x499602D2