Это действительно несколько вопросов в одном.
О this
...
Насколько я понимаю, использование this
предполагается совершенно излишним, но поддержка компилятором C++11 не совсем универсальна. Это должно работать в соответствии со стандартом С++ 11:
struct Base {
void func() noexcept;
};
struct Derived() {
void func() noexcept(noexcept(Base::func())) {}
};
Обратите внимание, что base_func()
— это нестатическая функция-член, но поскольку она появляется в невычисленном операнде, с ней все в порядке. Из n3337 сек 4.1.1:
id-expression, обозначающий нестатический член данных или нестатическую функцию-член класса, можно использовать только:
...
- если это id-expression обозначает нестатический элемент данных и появляется в невычисленном операнде.
Однако некоторые компиляторы этого не поддерживают. Затем вы вынуждены использовать std::declval
:
#include <utility>
struct Base {
void func() noexcept;
};
struct Derived() {
void func() noexcept(noexcept(std::declval<Base>().func())) {}
};
О доступности...
Я прочитал соответствующие части стандарта о невычисленных операндах и управлении доступом к элементам и пришел к выводу, что стандарт немного двусмыслен. В нем упоминается, что имя protected
может использоваться только участниками, друзьями и производными классами. Вопрос в том, используют ли невычисленные операнды имена членов, которые в них появляются. Они, конечно, не odr-используют имена элементов и даже могут использовать имена членов, если не предоставлено определение, и именно из-за такой двусмысленности термин odr-использование вообще существует! Например,
int f(); // No definition anywhere in program
int x = sizeof(f()); // Completely valid, even without definition of f
struct X {
X() = delete; // Cannot use this constructor
};
int xsize = sizeof(X{}); // Completely valid
Несмотря на то, что это несколько неясно, мне трудно представить, что комитет C++ мог разрешить вам использовать удаленные функции-члены в невычисленных операндах, но не недоступные функции-члены. Однако я не уверен.
Обратите внимание, что приведенный выше код компилируется без ошибок как с GCC, так и с Clang. Однако следующий код не работает:
class X {
X(){}
};
class Y {
Y() = delete;
};
bool xokay = noexcept(X{}); // Error!
bool yokay = noexcept(Y{}); // Ok
И GCC, и Clang принимают Y, но не X, что выглядит немного странно, если не сказать больше. Следующий код принимается Clang, но не GCC, и использование std::declval
не помогает:
class Base {
protected:
void func();
};
class Derived : public Base {
// Clang accepts this, GCC does not.
void func2() noexcept(noexcept(Base::func())) {}
};
Какой беспорядок.
Выводы
Вывод здесь состоит в том, что кажется, что есть много несоответствий, которые нужно обойти, и много пробелов между текущими компиляторами и спецификациями C++11.
person
Dietrich Epp
schedule
08.03.2016