Error c3646 noexcept неизвестный спецификатор переопределения

Учу C++ по книге, в конце главы есть задания и одно из них - сделать функцию подсчета символов в классе Document. При создании класса возникла проблема: при запуске программы появляется ошибка "C3646

Учу C++ по книге, в конце главы есть задания и одно из них — сделать функцию подсчета символов в классе Document. При создании класса возникла проблема: при запуске программы появляется ошибка «C3646 begin: неизвестный спецификатор определения». Такая же ошибка с функцией end();

document.h:

#include <list>
#include <vector>
#include <iostream>
using namespace std;

using Line = vector<char>;

struct Document {
    list<Line> line;
    Document() { line.push_back(Line{}); }

    Text_iterator begin() { return Text_iterator(line.begin(), line.begin()->begin()); } //здесь ошибка
    Text_iterator end() { return Text_iterator(line.end(), line.end()->end()); } //в этой строке так же

    int count();
};

istream& operator>> (istream& is, Document& d) {
    for (char ch; is.get(ch);) {
        d.line.back().push_back(ch);
        if (ch == 'n') d.line.push_back(Line{});

    }

    if (d.line.back().size()) d.line.push_back(Line{});

    return is;
}

class Text_iterator {
    list<Line>::iterator ln;
    Line::iterator pos;

public:
    Text_iterator (list<Line>::iterator ll, Line::iterator pp) : ln{ll}, pos{pp} {}
    char& operator* () { return *pos;  }

    Text_iterator& operator++ ();

    bool operator== (const Text_iterator& other) const { return ln == other.ln && pos == other.pos; }
    bool operator!= (const Text_iterator& other) const { return !(*this == other); }
};

задан 20 авг 2017 в 13:58

Alexen Mort's user avatar

Ну откуда же компилятору знать, что такое Text_iterator до его объявления?

Перенесите объявление класса Text_iterator перед классом Document.

Ответил только на ваш конкретный вопрос; верно ли все у вас будет после этого работать — не проверял…

ответ дан 20 авг 2017 в 14:06

Harry's user avatar

HarryHarry

210k15 золотых знаков115 серебряных знаков224 бронзовых знака

1

SadiQ228

-4 / 24 / 7

Регистрация: 16.12.2016

Сообщений: 716

1

23.07.2018, 00:22. Показов 5551. Ответов 2

Метки нет (Все метки)


C++
1
2
3
4
5
6
7
8
9
class xxx :public yyy
{
public:
    string str;
    int r;
    xxx(int r=0);
    void get();
    void set(int r);
};

подчеркивает строку где объявляется переменная string не понимаю в чем дело

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

23.07.2018, 00:22

2

lArtl

322 / 174 / 78

Регистрация: 09.10.2014

Сообщений: 809

23.07.2018, 03:06

2

выше напиши

C++
1
2
#include <string>
using namespace std;



0



-4 / 24 / 7

Регистрация: 16.12.2016

Сообщений: 716

23.07.2018, 03:07

 [ТС]

3

разобрался не везде подрубил инклуды



0



Я пытаюсь создать собственное исключение, которое происходит от std::exception и переопределяет what(), Сначала я написал это так:

class UserException : public std::exception
{
private:
const std::string message;
public:
UserException(const std::string &message)
: message(message)
{}

virtual const char* what() const override
{
return message.c_str();
}
};

Это прекрасно работает в VS2012, но не компилируется в GCC 4.8 с -std=c++11:

ошибка: более слабый спецификатор броска для «виртуального константного символа * UserException :: what () const»

Итак, я добавляю noexcept:

virtual const char* what() const noexcept override

Это хорошо работает в GCC, но не компилируется в Visual Studio (потому что VS 2012 не поддерживает noexcept):

ошибка C3646: «noexcept»: неизвестный спецификатор переопределения

Каков рекомендуемый способ борьбы с этим? Я хочу, чтобы один и тот же код компилировался с обоими компиляторами, и я использую функции C ++ 11, поэтому я не могу компилировать с разными -std,

43

Решение

Использовать макрос

#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif

А затем определить функцию как

virtual const char* what() const NOEXCEPT override

Вы также можете изменить это, чтобы noexcept в более поздних версиях VS, проверив значение _MSC_VER; для VS2012 значение составляет 1600.

43

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

«noexcept» поддерживается только начиная с Visual Studio 2015 (как указано здесь: https://msdn.microsoft.com/en-us/library/wfa0edys.aspx).
Я использовал следующий код с Visual Studio 2013 (полученный из приведенных выше примеров):

#if !defined(HAS_NOEXCEPT)
#if defined(__clang__)
#if __has_feature(cxx_noexcept)
#define HAS_NOEXCEPT
#endif
#else
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || 
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
#define HAS_NOEXCEPT
#endif
#endif

#ifdef HAS_NOEXCEPT
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif

15

Эта проверка работает, чтобы увидеть, если noexcept поддерживается:

// Is noexcept supported?
#if defined(__clang__) && __has_feature(cxx_noexcept) || 
defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || 
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180021114
#  define NOEXCEPT noexcept
#else
#  define NOEXCEPT
#endif

Вышеуказанное работает с Clang, GCC и MSVC.

12

использование BOOST_NOEXCEPT в <boost/config.hpp>

Библиотека config config была разработана для таких проблем совместимости. В соответствии с документ:

Если BOOST_NO_CXX11_NOEXCEPT определяется (то есть компиляторы, совместимые с C ++ 03), эти макросы определяются как:

    #define BOOST_NOEXCEPT
#define BOOST_NOEXCEPT_OR_NOTHROW throw()
#define BOOST_NOEXCEPT_IF(Predicate)
#define BOOST_NOEXCEPT_EXPR(Expression) false

Если BOOST_NO_CXX11_NOEXCEPT не определяется (то есть компиляторы, совместимые с C ++ 11), они определяются как:

    #define BOOST_NOEXCEPT noexcept
#define BOOST_NOEXCEPT_OR_NOTHROW noexcept
#define BOOST_NOEXCEPT_IF(Predicate) noexcept((Predicate))
#define BOOST_NOEXCEPT_EXPR(Expression) noexcept((Expression))

Многие другие ответы здесь имеют аналогичную реализацию, но эта библиотека чище, лучше протестирована и будет делать правильные вещи при обновлении вашего компилятора. Я рекомендую взглянуть на библиотеку boost config для других функций, особенно в это время языкового потока и различных уровней поддержки среди компиляторов.

9

noexcept Это один из самых простых недостатков MSVC: просто используйте макрос _NOEXCEPT который в MSVC2013 определен в yvals.h.

3

Добавьте следующие строки в ваш код в Visual Studio:

#ifdef _NOEXCEPT
#define noexcept _NOEXCEPT
#endif

3

Я недавно использовал следующее:

#ifdef _MSC_VER
#define NOEXCEPT _NOEXCEPT
#else
#define NOEXCEPT noexcept
#endif

а потом просто использовать NOEXCEPT везде.

2

Кажется, что старый throw() (устарело в C ++ 11) работает в обоих компиляторах. Поэтому я изменил код на:

virtual const char* what() const throw() override

1

I am getting the following error:

error C3646: ‘__attribute__’: unknown override specifier

Code:

LEMUR_PREALIGN char _stack[ sizeof(_Type) * _Count ] LEMUR_POSTALIGN;

Complete error:

1>c:program filesindriindri 5.9includeindrigreedy_vector(52): error C3646: ‘__attribute__’: unknown override specifier

Additional info: I am trying to use indri.lib in Visual Studio project.

Anders's user avatar

Anders

8,0979 gold badges53 silver badges85 bronze badges

asked Oct 3, 2015 at 13:27

Asim Saeed's user avatar

3

The __attribute__ command is a compiler specific command to gcc. And it is used on line 52 of this file with the ((align)) command, which:

Specifies a minimum alignment (in bytes) for variables of the specified type

Visual studio does in fact have a similar alignment command: align. But there are two problems:

  1. __declspec(align(#)) does not support the defaulted: __attribute__ ((aligned)) behavior which will:

Align a type to the maximum useful alignment for the target machine you are compiling for

  1. __declspec(align(#)) is a prefix. __attribute__((aligned(#))) is a suffix. This means that your actual code would need to differ on the placement:

struct S { short f[3]; } __attribute__ ((aligned)); // gcc alignment definition
__declspec(align(16)) strict S { short f[3]; }; // MSVC alignment

The point here is you’d probably be better off #ifdefing by compiler any line that uses __attribute__ ((aligned)) and cooking your own __declspec(align(#)).

For more info see: GCC vs MSVC class packing and alignment


After a bit more study into lemur_platform.h it looks like the code has already done all the above work for you! You’ll notice that #define LEMUR_POSTALIGN __attribute__ ((aligned)) is wrapped in an #ifndef WIN32. So what you need to do is define WIN32 in your Visual Studio project!

Community's user avatar

answered Oct 3, 2015 at 15:30

Jonathan Mee's user avatar

Jonathan MeeJonathan Mee

37.4k21 gold badges125 silver badges285 bronze badges

2

I am getting the following error:

error C3646: ‘__attribute__’: unknown override specifier

Code:

LEMUR_PREALIGN char _stack[ sizeof(_Type) * _Count ] LEMUR_POSTALIGN;

Complete error:

1>c:program filesindriindri 5.9includeindrigreedy_vector(52): error C3646: ‘__attribute__’: unknown override specifier

Additional info: I am trying to use indri.lib in Visual Studio project.

Anders's user avatar

Anders

8,0979 gold badges53 silver badges85 bronze badges

asked Oct 3, 2015 at 13:27

Asim Saeed's user avatar

3

The __attribute__ command is a compiler specific command to gcc. And it is used on line 52 of this file with the ((align)) command, which:

Specifies a minimum alignment (in bytes) for variables of the specified type

Visual studio does in fact have a similar alignment command: align. But there are two problems:

  1. __declspec(align(#)) does not support the defaulted: __attribute__ ((aligned)) behavior which will:

Align a type to the maximum useful alignment for the target machine you are compiling for

  1. __declspec(align(#)) is a prefix. __attribute__((aligned(#))) is a suffix. This means that your actual code would need to differ on the placement:

struct S { short f[3]; } __attribute__ ((aligned)); // gcc alignment definition
__declspec(align(16)) strict S { short f[3]; }; // MSVC alignment

The point here is you’d probably be better off #ifdefing by compiler any line that uses __attribute__ ((aligned)) and cooking your own __declspec(align(#)).

For more info see: GCC vs MSVC class packing and alignment


After a bit more study into lemur_platform.h it looks like the code has already done all the above work for you! You’ll notice that #define LEMUR_POSTALIGN __attribute__ ((aligned)) is wrapped in an #ifndef WIN32. So what you need to do is define WIN32 in your Visual Studio project!

Community's user avatar

answered Oct 3, 2015 at 15:30

Jonathan Mee's user avatar

Jonathan MeeJonathan Mee

37.4k21 gold badges125 silver badges285 bronze badges

2

Я пытаюсь создать настраиваемое исключение, которое происходит от std::exception и переопределяет what(). Сначала я написал это следующим образом:

class UserException : public std::exception
{
private:
    const std::string message;
public:
    UserException(const std::string &message)
        : message(message)
    {}

    virtual const char* what() const override
    {
        return message.c_str();
    }
};

Это отлично работает в VS2012, но не компилируется в GCC 4.8 с -std=c++11:

error: looser throw specifier для ‘virtual const char * UserException:: what() const

Итак, я добавляю noexcept:

virtual const char* what() const noexcept override

Это отлично работает в GCC, но не компилируется в Visual Studio (потому что VS 2012 не поддерживает noexcept):

ошибка C3646: «noexcept»: неизвестный спецификатор переопределения

Каков рекомендуемый способ справиться с этим? Я хочу, чтобы один и тот же код компилировался с обоими компиляторами, и я использую С++ 11, поэтому я не могу скомпилировать с помощью -std.

Понравилась статья? Поделить с друзьями:
  • Error c3493 cannot be implicitly captured because no default capture mode has been specified
  • Error c2976 std vector слишком мало аргументов шаблон
  • Error c2908 явная специализация уже создан экземпляр
  • Error c2804 binary operator has too many parameters
  • Error c2784 c