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