Използване на оператора noexcept за свързване на noexcept декларации

Защо операторът noexcept приема израз, а не сигнатура/декларация на функция?

Помислете за следния фиктивен пример:

#include <string>

void strProcessor(const std::string& str) noexcept(true) { };

struct Type{
  void method1() noexcept(strProcessor("")) { //Error: Call to nonconstexpr function
     strProcessor("");
  }
};

Няма да се компилира, защото method1 има израз, който не е constexpr, в noexcept, но защо изобщо трябва да поставя израз там?

Всичко, което искам да направя, е да кажа на компилатора, че method1 е noexcept, ако извикването на strProcessor с успешно конструиран низ е noexcept (което е).

Така че защо не noexcept(void strProcessor(const std::string&))?

Друг подобен фиктивен пример:

struct Type{
   Type(bool shouldThrow=false) noexcept(false) { if(shouldThrow) throw "error"; };
   void method1() noexcept(true) {};
   void method2() noexcept(noexcept(Type().method1())) { method1(); };
}

Тук бих искал да кажа, че method2 е noexcept, ако извикването на method1 на успешно конструиран екземпляр на Type е noexcept (което е в този случай), но Type дори не е завършено в точката, където method2 ID дефиниран.

Моля, обяснете, ако разбирам погрешно тази функция.


person PSkocik    schedule 27.07.2015    source източник
comment
Е, тук има гъвкавост, тъй като тогава можете да правите по-умни неща от простото именуване на функция. Изразът няма да бъде оценен, така че можете да използвате declval и приятели, за да избегнете странични ефекти и т.н. Наистина не разбирам грешката обаче, тъй като не съм много запален нито по noexcept, нито по constexpr.   -  person Lightness Races in Orbit    schedule 27.07.2015


Отговори (2)


void method1() noexcept(noexcept(strProcessor(""))) {
//   Second 'noexcept'  ^^^^^^^^^                ^

Първият е noexcept спецификатор, който < strong>указва дали method1() е noexcept или не.

Вложеният е noexcept оператор, който < силна>проверява дали strProcessor() е noexcept при извикване с "".

Вашият втори случай е малко сложен: Type все още е незавършен в точката, в която бихме искали да използваме method1() вътре в noexcept. Стигнах до следното решение, злоупотребявайки с указател към член:

void method2() noexcept(noexcept(
    (std::declval<Type>().*&Type::method1)()
)) {};

Въпреки това, не мисля, че има случай, в който можете да изведете само спецификацията noexcept на method2() от тази на method1().

person Quentin    schedule 27.07.2015
comment
Благодаря! Можете ли да коригирате и втория пример? - person PSkocik; 27.07.2015

Ако искате малко синтактична захар, когато проверявате noexceptness на функция, можете да използвате спомагателна функция като така:

template <typename R, typename... Params>
constexpr bool is_noexcept(R(*p)(Params...)) {
    return noexcept(p(std::declval<Params>()...));
}

И прилагайте по този начин:

void method1() noexcept(is_noexcept(strProcessor)) …

Демо.

person Columbo    schedule 27.07.2015