Учу 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
Ну откуда же компилятору знать, что такое Text_iterator
до его объявления?
Перенесите объявление класса Text_iterator
перед классом Document
.
Ответил только на ваш конкретный вопрос; верно ли все у вас будет после этого работать — не проверял…
ответ дан 20 авг 2017 в 14:06
HarryHarry
210k15 золотых знаков115 серебряных знаков224 бронзовых знака
1
SadiQ228 -4 / 24 / 7 Регистрация: 16.12.2016 Сообщений: 716 |
||||
1 |
||||
23.07.2018, 00:22. Показов 5551. Ответов 2 Метки нет (Все метки)
подчеркивает строку где объявляется переменная 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 |
|||
выше напиши
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
8,0979 gold badges53 silver badges85 bronze badges
asked Oct 3, 2015 at 13:27
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:
__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
__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 #ifdef
ing 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!
answered Oct 3, 2015 at 15:30
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
8,0979 gold badges53 silver badges85 bronze badges
asked Oct 3, 2015 at 13:27
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:
__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
__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 #ifdef
ing 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!
answered Oct 3, 2015 at 15:30
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
.