Ошибка спецификации динамического исключения c ++ 1z

Я пытаюсь скомпилировать свой проект с новой версией GCC 7.2.1 и у меня возникли проблемы со спецификациями динамических исключений:

error: ISO C++1z does not allow dynamic exception specifications
MEMORY_ALLOC_OPERATORS(SQLException)

Проблема в том, что эти ошибки происходят из сторонних библиотек, которые я не контролирую.

Есть ли какой-нибудь способ это исправить? Насколько я знаю, я не могу сказать компилятору заменить ошибки предупреждениями. С помощью --std=c++14 это не вариант, потому что я хочу использовать новые функции из C ++ 1z.

8

Решение

C ++ 17 удалил спецификации динамических исключений, в результате P0003. До этого они были устаревшими с C ++ 11. Они больше не являются частью языка, поэтому на самом деле нет способа исправить это. Пока вам нужна эта сторонняя библиотека, пока она не изменится, вы застряли на C ++ 14.


Если вы в отчаянии, вы можете попробовать:

#define throw(...)

но я бы не рекомендовал это.

7

Другие решения

Ну, я написал небольшой обходной путь.

#if __cplusplus >= 201703L
/* MySQL override. This needed to be inclided before cppconn/exception.h to define them */
#include <stdexcept>
#include <string>
#include <memory>

/* Now remove the trow */
#define throw(...)
#include <cppconn/exception.h>
#undef throw /* reset */
#endif

Краткое объяснение:
Если мы используем c ++ 17, throw больше не разрешен для распределителей.
Если вы внимательно посмотрите на заголовок библиотеки, вы увидите, что существует определенный макрос, который содержит определения для распределителя по умолчанию в библиотеке. К сожалению, его нельзя переопределить, потому что он определен там, игнорируя то, что уже может быть определено. Так или иначе, вы все равно должны отвергнуть дроу.

Основная хитрость заключается в переопределении функции trow с помощью макроса.
Это приводит нас к проблеме, что мы также переопределяем оператор trow для всех включений в библиотеке, что не является хорошим решением (а также не работает).
Как вы, возможно, знаете, если вы включаете заголовок, он будет включен только один раз (в основном, благодаря защите заголовков).
Таким образом, хитрость заключается в том, чтобы включить заголовки, которые включены библиотекой, а затем переопределить бросок, включив заголовок целевой библиотеки, которая фактически не включает их заголовок снова, потому что мы уже это сделали.

2

  1. Слой изоляции, как упомянуто, как упомянуто в комментарии выше. Что-то вроде:

#if __cplusplus < 201703L // Standards below C++2017

 void fn() throw (int) { }

#endif // __cplusplus

  1. Давно пора заняться заменой throw(whatever) с noexcept(fasle),

В любом случае, будьте готовы повеселиться!

1

Столкнулся с той же проблемой, поэтому мне пришлось изменить это определение макроса в /usr/include/cppconn/exception.h:

#define MEMORY_ALLOC_OPERATORS(Class) \
void* operator new(size_t size) noexcept(false) { return ::operator new(size); }  \
void* operator new(size_t, void*) noexcept; \
void* operator new(size_t, const std::nothrow_t&) noexcept; \
void* operator new[](size_t) noexcept(false); \
void* operator new[](size_t, void*) noexcept; \
void* operator new[](size_t, const std::nothrow_t&) noexcept; \
void* operator new(size_t N, std::allocator<Class>&);
1
По вопросам рекламы [email protected]