2016-03-08 19 views
7

Proszę rozważyć następujący fragment kodu:Czy możemy odnieść się do zmiennych członkowskich w specyfikacji noexcept?

template<class Tuple> 
class vector 
{ 
public: 
    typename Tuple::size_type size() const noexcept(noexcept(m_elements.size())) { 
     return m_elements.size(); 
    } 

private: 
    Tuple m_elements; 
}; 

class tuple 
{ 
public: 
    using size_type = std::size_t; 

    size_type size() const { return 0; } 
    size_type size() noexcept { return 0; } 
};  

int main() 
{ 
    vector<tuple> x; 
    static_assert(noexcept(x.size()), "x.size() might throw"); 

    return 0; 
} 

jest użycie zmiennej członkiem m_elements wewnątrz noexcept specifier legalne? GCC 5.2 (C++17) yields the compiler errorm_elements nie został zadeklarowany w tym zakresie. podczas gdy clang 3.6 (C++17) compiles without any error.

Oba kompilatory nie dają błędu, jeśli zamiast tego użyję noexcept(std::declval<Tuple const&>().size()). Jednak, jak widać, stworzyłem prostą przykładową klasę tuple, gdzie ważne jest, czy Tuple czy nie kwalifikował przeciążenia size.

Z mojego punktu widzenia, jest to bardziej intuicyjne napisać noexcept(m_elements.size()) bo to jest dokładnie to wywołanie w organizmie funkcji i bierze pod uwagę, że metoda vectorsize jest const kwalifikacje (co sprawia m_elements const obiektu w zakresie funkcja).

Jakie jest prawne użycie? Jeśli oba są równoważne, co powinienem użyć? Czy w tym scenariuszu powinienem w ogóle używać kwalifikatorów noexcept? Problem polega na tym, że niezależnie od tego, czy funkcje vector będą się wyświetlać, zależy w każdym przypadku od Tuple.

+0

Chciałbym zauważyć, że istnieje [pytanie dotyczące użycia zmiennych członkowskich w specyfikacji "noexcept"] (http://stackoverflow.com/questions/27241938/noexcept-depending-on-method-of -member) tutaj na tablicy, ale proszę zauważyć, że to pytanie jest związane z C++ 11 i błędem kompilatora generowanym przez (nieznaną wersję) clanga. – 0xbadf00d

Odpowiedz

5

Clang jest tutaj poprawny, jest to błąd w gcc. Według [basic.scope.class], kopalnia nacisk:

Potencjalny zakres nazwy zadeklarowanej w klasie składa się nie tylko z regionu deklaratywnej następstwie imienia punktu deklaracji, ale również wszystkich organów funkcyjnych, domyślne argumenty, wyjątek -specyfikacje i ortokwasów lub inicjatorów równych niestatycznych elementów danych w tej klasie (włącznie z takimi obiektami w zagnieżdżonych klasach ).

Zakres m_elements zawiera noexcept specyfikacją dla size().