2016-03-08 4 views
7

Пожалуйста, обратите внимание на следующий фрагмент кода:Можем ли мы ссылаться на переменные-члены в спецификации 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; 
} 

является использование переменной-члена m_elements внутри noexcept спецификатор законно? GCC 5.2 (C++17) yields the compiler errorm_elements не был заявлен в этой области. а clang 3.6 (C++17) compiles without any error.

Оба компилятора не выдают ошибку, если я использую вместо этого noexcept(std::declval<Tuple const&>().size()). Однако, как вы можете видеть, я создал простой пример класса tuple, где важно, имеет ли Tuple квалификационные перегрузки size.

С моей точки зрения, это более интуитивным писать noexcept(m_elements.size()) потому что это именно вызов в теле функции, и принимает во внимание, что size метод vector является const правомочно (что делает m_elements константный объект в рамках функция).

Итак, каково правовое использование? Если оба эквивалентны, что я должен использовать? Должен ли я использовать квалификаторы noexcept вообще в этом сценарии? Проблема в том, что независимо от того, будут ли выполняться функции vector, во всем большинстве случаев на Tuple.

+0

Я хотел бы отметить, что существует [вопрос о применении переменных-членов в спецификации 'noexcept'] (http://stackoverflow.com/questions/27241938/noexcept-depending-on-method-of -member) здесь, но обратите внимание, что этот вопрос связан с C++ 11 и ошибкой компилятора, созданной (некоторой неизвестной версией) clang. – 0xbadf00d

ответ

5

Clang здесь правильно, это ошибка gcc. Согласно [basic.scope.class], курсив мой:

Потенциальная область видимости имени, объявленному в классе состоит не только из декларативной области ниже точек имени в декларации, но и все функции органов, аргументы по умолчанию, исключения -специфики и скобки-равные-инициализаторы нестатических данных в этом классе (включая такие вещи в вложенных классах).

Объем m_elementsвключает noexcept спецификацию для size().

Смежные вопросы