Error overloaded function with no contextual type information

  • Forum
  • Beginners
  • overload error

overload error

Hello, so im getting overload function with no contextual type information at lines 124 & 131 . Any help would be appreciated

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#ifndef Guess_h
#define Guess_h
#include <iostream>
#include <string>
#include <algorithm>  // used for sort
#include <vector>  // for vector
#include <sstream>
#include <fstream>
#include <limits>
#include <cstdlib>
using namespace std;

/////////////////////////
// Player Class
/////////////////////////

class Player 
{
public:
virtual int getGuess() = 0;
virtual void lastGuess(int result) = 0;
virtual void lastGuess1(int result) = 0;
virtual void hGuess2(double result) = 0;
virtual void hGuess3(double result) = 0;
};


/////////////////////////
// ComputerPlayer Class
/////////////////////////

class ComputerPlayer : public Player
{
public:
ComputerPlayer();
int getGuess();
virtual void lastGuess(int result);
virtual void lastGuess1(int result);
virtual void hGuess2(double result) {};
virtual void hGuess3(double result) {};
void setmin(int mi) {min = mi;};
void setmax(int ma) {max = ma;};
int returnGuess() {cout << guess << endl;return guess;}

private:
int min = 0, max = 99;
// Bounds to guess within
int guess;
// The guess we made
};

ComputerPlayer::ComputerPlayer() : Player()
{
min = 0;
max = 99;
guess = 0;

}

int ComputerPlayer::getGuess()
{
// Make guess where min < guess <= max
int guess = (rand() % (max -min)) + min;
cout << "The computer guesses " << guess << endl;
// Remember the guess
this->guess = guess;
return guess;
}

// Tells the computer player if the last guess was
// too low or too high.  This version only gets feedback
// on our own guess, not on the opponent's guess.  It would
void ComputerPlayer::lastGuess(int result)
{
// implement your code here

		cout << "last guess function high " << endl;
	//max = result;
	setmax(result);
		//cout << max << end;
guess = result;
}
void ComputerPlayer::lastGuess1(int result)
{
// implement your code here
		cout << "last guess function low " << endl;
		//min = result;
		setmin(result);
		cout << min << endl;
guess = result;
}
/////////////////////////
// HumanPlayer Class
/////////////////////////
class HumanPlayer : public Player
{
public:
HumanPlayer();
int getGuess();
virtual void lastGuess(int result) {};
virtual void lastGuess1(int result) {};
virtual void hGuess2(double result);
virtual void hGuess3(double result);

private:
int guess;
};
HumanPlayer::HumanPlayer() : Player()
{
}
int HumanPlayer::getGuess()
{
	cout << "Please enter your guess: " << endl;
	cin >> guess;
//implement your code here
// Ask user to input guess
//  get guess from the human player
return guess;
}

void HumanPlayer::hGuess2(double result)
{
	cout << "I want to change the max " << endl;
	 max = result;                  // ***************** This is where error

// Do nothing, human can see the screen
}
void HumanPlayer::hGuess3(double result)
{
		cout << "I want to change the min " << endl;
		min = result;          // ***************** This is where error

// Do nothing, human can see the screen
}

//////////////////////////////////////
// Global functions 
//////////////////////////////////////
bool checkForWin(int guess, int answer, Player &p)
{
	bool win = false;
	if (guess > answer)
	{
		cout << "Your guess was to high " << endl;
		p.lastGuess(guess);
				p.hGuess2(guess);
		win = false; 
	}
	else if(guess < answer)
	{
		cout << "Your guess was to low " << endl;
		p.lastGuess1(guess);
		p.hGuess3(guess);
		win = false; 
	}
	if ( guess == answer)
	{
		cout << "You win!!!" << endl;
		win = true; 
	}
//  if the guess is same as answer. The player wins.
//  if the guess is not the same as answer
//  inform the palyer if the guess is too high or too low
//  and keep track of last guess
// 
return win;
}
void play(Player &player1, Player &player2)
{
int answer = 0, guess = 0;
answer = rand() % 100;
cout << answer << endl;
// get an ramdom answer for play to guess
bool win = false;
while (!win)
{
cout << "Player 1's turn to guess." << endl;
guess = player1.getGuess();
win = checkForWin(guess, answer, player1);
if (win) return;
cout << "Player 2's turn to guess." << endl;
guess = player2.getGuess();
win = checkForWin(guess, answer, player2);
}
}

Last edited on

Hi,

This might be because of line 11. std::min and std::max are defined in the algorithm header.

using namespace std; is a bad habit, now might be the time to break it :+)

If you look at the code provided by many of the experienced users here, they always put std:: before each std thing. It’s the best way. There are other alternatives, but doing that is the best in the end.

Some other things to help you out:

When overriding a pure virtual function, use the override keyword. C++11

Consider using the member initilization list rather than assignment in the constructor.

Use const more, for member functions that don’t change the state of the object, in function parameters, and basically where ever you can.

Good Luck !!

Thank you!!! just changing the variable names from max/ min to high/lo fixed it!!

Ive always wondered why is it a bad habit to use using namespace std;. What are the down sides? and what are the benefits to using std::

What are the down sides? and what are the benefits to using std::

Well the main downside you have already encountered: name clashes. That is the whole point of namespaces — to avoid name clashes, using namespace std; subverts that in a big way by bringing in all of the STL (as defined by whatever include files there are) into the global namespace and polluting it. There are lots of examples of normal words used in the STL: left, right, distance to name just a few.

Ideally one should put their own code into it’s own namespaces.

Also, when one uses std:: , it specifies which thing one is using. For example, std::copy , not boost::copy , or copy from some other library.

Another thing I noticed in your code: Avoid using std::endl , it flushes the buffer every time, so could be inefficient. Just use «n» instead:

std::cout << "Player 1's turn to guess.n";

Last edited on

Topic archived. No new replies allowed.

mster-doc

16 / 16 / 12

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

Сообщений: 245

1

Нужно разобратся, ошибка

19.12.2012, 23:26. Показов 3854. Ответов 2

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


Здравствуйте. Компилятор выдаёт ошибку в строке

C++
1
find = true;
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
       
 
...
 
cout << " Print the debtors "<< endl;
              
              int a = 0;
              
              clientData m[size];
              
              for(int i = 0; i < size; ++i)
                 {
                         if(m[i].balance < a)
                         {
                                        find = true;
                                        cout << " Account number:" << m[i].accNum
                                             << "n User name:" << m[i].Name
                                             << "n User surname:" << m[i].Sur
                                             << "n Balance:" << m[i].balance << endl;
                                             
                         }
                 }
                 
                 if(!find)
                 {
                          cout << " Not debtorsn";
                 }
...

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



0



Don’t worry, be happy

17781 / 10545 / 2036

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

Сообщений: 26,516

Записей в блоге: 1

19.12.2012, 23:30

2

Цитата
Сообщение от mster-doc
Посмотреть сообщение

Здравствуйте.

Цитата
Сообщение от mster-doc
Посмотреть сообщение

Компилятор выдаёт ошибку в строке

Ну тут телепатов нет. Неизвестно что такое find, нет ни описания, ни кода ошибки.
И если уж на то пошло, то find — это функция. А если это Ваша переменная, то переименуйте её. Тут скорее всего конфликт имен. Но всё же телепатией я плохо владею



0



16 / 16 / 12

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

Сообщений: 245

19.12.2012, 23:38

 [ТС]

3

… Untitled1.cpp overloaded function with no contextual type information
перегруженная функция, не контекстную информацию типа

както так

Добавлено через 4 минуты
я разобрался, точно, я забыл прописать часть кода
bool find = false;



0



Содержание

  1. Ошибка компиляции при попытке установить пакеты на R4.0 с использованием RTools
  2. 2 ответа
  3. перегруженная функция без информации о контекстном типе | не может разрешить перегруженную функцию swap на основе преобразования в тип int
  4. 3 ответы
  5. C ++ с использованием стандартных алгоритмов со строками, count_if с isdigit, приведение функций
  6. Решение
  7. Другие решения
  8. C++ используя стандартные алгоритмы со строками, count if with isdigit, функция cast
  9. 4 ответов
  10. Помоги компилятору помочь тебе
  11. Предисловие
  12. Содержание
  13. Ода компилятору
  14. Игнорировать нельзя исправить
  15. -Waddress
  16. -Warray-bounds=1
  17. -Wbool-compare
  18. -Wbool-operation
  19. -Wcatch-value
  20. -Wchar-subscripts
  21. -Wcomment
  22. -Wint-in-bool-context
  23. -Winit-self
  24. -Wlogical-not-parentheses
  25. -Wmaybe-uninitialized
  26. -Wmemset-elt-size
  27. -Wmemset-transposed-args
  28. -Wmisleading-indentation
  29. -Wmissing-attributes
  30. -Wmultistatement-macros
  31. -Wnonnull
  32. -Wnonnull-compare
  33. -Wparentheses
  34. -Wpessimizing-move
  35. -Wreorder
  36. -Wreturn-type
  37. -Wsequence-point
  38. -Wsign-compare
  39. -Wsizeof-pointer-div
  40. -Wsizeof-pointer-memaccess
  41. -Wstrict-aliasing
  42. -Wswitch
  43. -Wtautological-compare
  44. -Wtrigraphs
  45. -Wuninitialized
  46. -Wunused-function
  47. -Wunused-variable
  48. -Wextra
  49. -Wempty-body
  50. -Wimplicit-fallthrough
  51. -Wmissing-field-initializers
  52. -Wredundant-move
  53. -Wtype-limits
  54. -Wshift-negative-value
  55. -Wunused-parameter
  56. -Wunused-but-set-parameter
  57. -Wpedantic
  58. Нужно больше предупреждений
  59. -Wctor-dtor-privacy
  60. -Wnon-virtual-dtor
  61. -Wold-style-cast
  62. -Woverloaded-virtual
  63. -Wsign-promo
  64. -Wduplicated-branches
  65. -Wduplicated-cond
  66. -Wfloat-equal
  67. -Wshadow=compatible-local
  68. -Wcast-qual
  69. -Wconversion
  70. -Wzero-as-null-pointer-constant
  71. -Wextra-semi
  72. -Wsign-conversion
  73. -Wlogical-op
  74. -Werror
  75. Заключение

Ошибка компиляции при попытке установить пакеты на R4.0 с использованием RTools

Мне нужно установить пакет ‘yags’, чтобы соответствовать GEE. Тем не менее, у меня есть проблемы во время процесса установки: и код возвращает ошибку. (Я использую версию R 4.0.0 (2020-04-24), платформа: x86_64-w64-mingw32 / x64 (64-разрядная версия), а также у меня установлены последние версии RStudio и RTools)

Кто-нибудь может понять, что может пойти не так?

Я знаю, что этот конкретный пакет требует ‘многоядерный’ в качестве зависимости, поэтому я попытался установить этот пакет заранее, используя архивы в CRAN, но также получил сообщение об ошибке того же типа:

2 ответа

Оба пакета больше не являются стандартными R-пакетами, поэтому нет гарантии, что они могут быть установлены «конечными пользователями». R-Forge является сервером разработки, и пакет «многоядерный» был заархивирован. CRAN предлагает вместо этого использовать пакет параллельный . Поскольку параллельный является базовым пакетом, он уже существует и не требует установки.

Тогда давайте перейдем к пакету яги : глядя на R-Forge, мы находим

Так что это выглядит довольно устаревшим. Поэтому я бы рекомендовал либо связаться с автором оригинального пакета, либо искать альтернативную и, возможно, более свежую реализацию, например, rjags или для поиска в сети gee R cran или jags R .

ОБНОВЛЕНИЕ (оставив первоначальный вопрос, если кто-то сталкивается с той же проблемой)

Я связался с автором пакета yags и установил его из GitHub, а не из репозитория R-Forge:

Источник

перегруженная функция без информации о контекстном типе | не может разрешить перегруженную функцию swap на основе преобразования в тип int

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

задан 15 фев ’12, 23:02

Где сообщения об ошибках? — iammilind

Извините: перегруженная функция без информации о контекстном типе не может разрешить перегруженную функцию swap на основе преобразования в тип int — Jonathan Dewein

Он запрашивал номер строки, которую компилятор указал в ошибке. — Alexander Kondratskiy

3 ответы

Я вижу что вы используете

Итак, когда вы набираете

Компилятор не может однозначно определить, имеете ли вы в виду std::swap функция или ваш int swap Переменная. На самом деле похоже, что вы предполагали, что вы имеете в виду функцию, и пытались как-то преобразовать ее в тип int . Попробуйте переименовать вашу переменную во что-нибудь другое.

В общем, старайтесь держаться подальше от using директивы, чтобы избежать подобных конфликтов имен.

Эта линия вызывает проблему. Лучше сменить имя swap локальная переменная, поскольку уже существует функция с таким же именем в std пространство имен, которое попадает в область видимости строкой using namespace std; чего в любом случае следует избегать.

Я также предлагаю вам объявить переменную внутри блока if, где она на самом деле используемый:

Лучшая практика: уменьшите локальные переменные области видимости, отложив их объявления, что означает объявление их там, где они фактически используются. Не объявляйте их в начале функции.

Другой способ исправить проблему в вашем коде — дать компилятору контекст что вы можете сделать это (хотя я бы не стал предлагать это решение; это просто для вас знать):

Когда вы бросаете swap в int , компилятор может знать, что swap относится к локальной переменной, а не к функции, которая определена в std пространство имен.

Ох . Я ничего не знаю о «информации о контекстном типе», которую можно явно указать таким образом. — яммилинд

@iammilind: Очень часто, когда вы перегружаете функции, вы упоминаете напишите функции, либо с явным приведением, либо как целевой тип. Скажем, есть много перегруженных функций с именем f в вашем проекте, тогда auto x = f выдаст ошибку компиляции с неоднозначным именем функции. Чтобы решить эту проблему, либо вы пишете ftype x = f или auto x = (ftype)f , Где ftype — это тип функции, которую вы намеревались использовать. — Наваз

Тип возвращаемого значения функции — void . Не на что печатать. Если вам нужно распечатать отсортированный массив, вам нужно выполнить итерацию по элементам массива после вызова функции.

Источник

C ++ с использованием стандартных алгоритмов со строками, count_if с isdigit, приведение функций

Я хочу посчитать все числа в строке кратчайшим способом. Я попробовал так:

Сообщение об ошибке:

Я знаю, что count_if () хочет функцию как:
bool (* f) (char); в качестве третьего аргумента, поэтому я попытался привести функцию:

Сообщение об ошибке:

Я попробовал также немного более длинную версию, которая дает ту же ошибку компиляции:

Решение, которое я хочу избежать, состоит в том, чтобы создать функцию, которая была бы адаптером:

Мой вопрос: как я могу использовать функции int (* f) (int) в функциях std :: алгоритма, которые хотят использовать bool (* f) (int) без создания функций адаптера и без использования лямбда-выражений?

У меня есть больше проблем, которые будут решены, когда я узнаю, как решить проблему, например:

  • Проверьте, пригодна ли строка для печати: find_if_not (s.begin (), s.end (), isprint)
  • Проверьте, содержит ли строка «. …»: find_if (s.begin (), s.end (), ispunct)
    и больше…

Я просто хочу знать, как получить гораздо больше возможностей для строк в стандартном C ++ благодаря std :: алгоритмов
Я долго искал в интернете, нашел аналогичная проблема , но я не нашел решения

Решение

Вы можете разрешить функцию, используя статическое приведение. В качестве альтернативы, если это то, что вы хотите сделать много, вы можете использовать шаблон для его решения:

static_cast это «обычный» способ разрешения неоднозначных — он всегда делает то, что вы ожидаете, и может быть частью более широкого выражения.

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

Разрешите тип, используя указатель на функцию:

Не забудьте включить , (демонстрация )

Я также нашел следующие работы:

но я должен выяснить, что это работает, только если версия C определена как функция
а не макрос

таким образом, static_cast из std :: isdigit может быть лучшим переносимым решением среди платформ.

Я дам 2 других решения, чтобы исправить неоднозначность с std::isdigit

или с явным приведением:

  1. Используйте явные типы шаблонов (вам также нужно написать тип итератора):

Источник

C++ используя стандартные алгоритмы со строками, count if with isdigit, функция cast

Я хочу подсчитать все числа в строке самым коротким способом кода. Я попробовал так:

сообщение об ошибке:

Я знаю, что count_if() хочет функционировать, как: bool (*f) (char); в качестве третьего аргумента, поэтому я попытался привести функцию:

сообщение об ошибке:

я попробовал также немного более длинную версию, которая дает ту же ошибку компиляции:

решение, которого я хочу избежать, — это создать функция, которая будет адаптером:

мой вопрос в том, как я могу использовать функции int(*f)(int) в функциях std::алгоритма, которые хотят bool(*f)(int) без создания адаптерных функций и без использования лямбда-выражений?

у меня есть больше проблем, которые будут решены, когда я узнаю, как решить проблему, например:

  • проверить, если строка печати: find_if_not(С. начать(), С. конец(), isprint)
  • проверьте, если строка содержит «. «: find_if (С. начать(), С. конец(), ispunct) и еще.

Я просто хочу знать, как иметь гораздо больше возможностей строки в стандартном C++ благодаря std:: алгоритмам Я искал в Интернете долгое время, я нашел похожие проблемы, но я не нашел решения

4 ответов

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

static_cast — это «обычный» способ разрешения неоднозначны — он всегда делает то, что вы ожидаете, и может быть частью большего выражения.

Источник

Помоги компилятору помочь тебе

Предисловие

Современные компиляторы обладают огромным количеством диагностик. И удивительно, что очень малая их часть включена по умолчанию.

Огромное количество претензий, которые предъявляют к языку C++ в этих ваших интернетах, — про сложность, небезопасность, стрельбу по ногам и т.п., — относятся как раз к тем случаям, когда люди просто не знают о том, что можно решить эти проблемы лёгким движением пальцев по клавиатуре.

Давайте же исправим эту вопиющую несправедливость, и прольём свет истины на возможности компилятора по предотвращению ошибок.

Содержание

Ода компилятору

Компилятор – лучший друг плюсовика. Компилятор — это не просто транслятор формального человекочитаемого языка в машинные коды. Компилятор — лучший помощник в написании программ.

Важная (и не единственная) помощь, которую оказывает компилятор — поиск ошибок. И я говорю не об опечатках, несовпадении типов и прочих синтаксических ошибках. Я говорю об огромном наборе ошибок, которые можно выловить с помощью механизма предупреждений.

Часто встречаю мнение о том, что предупреждений слишком много, они дают ложноположительные результаты, мешают работать, замыливают глаз, отвлекают от «настоящих» ошибок и т.п. Такое действительно бывает, но это большая редкость.

Игнорировать нельзя исправить

Большинство предупреждений — это не «бзик» компилятора, который можно просто проигнорировать. Предупреждение — это потенциальная ошибка. Предупреждение — это сигнал от компилятора о том, что написано одно, а требуется, возможно, что-то совершенно иное.

Поэтому программист должен помочь компилятору понять, как трактовать спорную ситуацию. То есть либо поправить свою ошибку, либо сообщить компилятору явно о том, что нужно верить программисту и делать именно то, что написано. Причём это поможет не только компилятору, но и человеку, который будет читать код. Лишний static_cast или пара скобок будут явно свидетельствовать о том, что имелось в виду именно то, что написано.

Далее я расскажу о наиболее важных на мой взгляд предупреждениях и покажу, какие ошибки можно отловить с их помощью.

Надеюсь, что данное не слишком занимательное чтиво поможет правильно поставить запятую в заголовке этого раздела.

Сразу хочу оговориться, что далее речь пойдёт исключительно о языке C++ и компиляторе GCC (впрочем, подавляющая часть информации актуальна и для компилятора Clang). Информацию о других компиляторах и языках придётся искать в соответствующих справочниках.

-Wall — это «агрегатор» базовых предупреждений. В языке C++ он включает в себя длинный перечень предупреждений, каждое из которых будет рассмотрено отдельно (на самом деле, рассмотрены будут не все, а только те, которые непосредственно помогают выявлять ошибки).

Несмотря на название, этот флаг включает далеко не все предупреждения, которые умеет обнаруживать компилятор.

-Waddress

Предупреждает о странной работе с адресами. Например, об использовании адреса функции в условном выражении. Такое может произойти, если забыть поставить скобки после имени функции:

Также этот флаг может спасти от типичной ошибки новичка — сравнения строкового литерала с адресом. Очевидно, программист хотел сравнить строки, но в результате сравнил два указателя:

-Warray-bounds=1

Предупреждает о выходе за пределы массивов. Используется только вместе с -O2 .

-Wbool-compare

Предупреждает о сравнении булева выражения с целым числом, которое нельзя трактовать как булево:

-Wbool-operation

Предупреждает о подозрительных операциях с булевыми выражениями. Например, о побитовом отрицании:

Что касается инкрементов и декрементов булевых переменных, то в C++17 это просто ошибки, безо всяких предупреждений.

-Wcatch-value

Предупреждает о обработчиках исключений, которые принимают полиморфные объекты по значению:

Есть и более сильные версии предупреждения: -Wcatch-value=n (см. справку к компилятору).

-Wchar-subscripts

Предупреждает об обращении к массиву по индексу, тип которого char . А ведь char является знаковым на многих машинах:

Предупреждает о наличии последовательности, начинающей новый комментарий ( /* ), внутри многострочного комментария, либо о разрыве строки при помощи обратного слеша внутри однострочного комментария.

-Wint-in-bool-context

Предупреждает о подозрительном использовании целых чисел там, где ожидаются булевы выражения, например, в условных выражениях:

Другой пример — операции побитового сдвига в булевом контексте. Вполне вероятно, что здесь произошла опечатка, и имелся в виду не сдвиг, а сравнение:

А также сообщает о любых видах умножения в булевом контексте.

-Winit-self

Предупреждает об инициализации переменных самими сабями. Используется только вместе с флагом -Wuninitialized .

-Wlogical-not-parentheses

Предупреждает об использовании логического отрицания в левой части сравнения. При этом если правая часть сравнения является сама по себе булевым выражением, то предупреждения не будет.

Используется для того, чтобы отлавливать подозрительные конструкции вроде следующей:

Традиционный способ сообщить компилятору, что так и было задумано — поставить скобки, о чём и сообщает компилятор.

-Wmaybe-uninitialized

Предупреждает о том, что существует возможность использования непроинициализированной переменной.

В данном конкретном случае решается с помощью конструкции default :

-Wmemset-elt-size

Предупреждает о подозрительных вызовах функции memset , когда первый аргумент — это массив, а третий аргумент — количество элементов в массиве, но не количество байт, занимаемой этим массивом в памяти.

-Wmemset-transposed-args

Предупреждает о том, что пользователь, вероятно, перепутал порядок аргументов в функции memset :

-Wmisleading-indentation

Предупреждает о том, что отступы в коде не отражают структуру этого кода. Особенно это актуально для конструкций if , else , while и for . Пример:

-Wmissing-attributes

Предупреждает о ситуации, когда специализация шаблона объявлена не с тем же списком атрибутов, что и оригинальный шаблон.

-Wmultistatement-macros

Предупреждает о макросах, состоящих из нескольких инструкций, и используемых в выражениях if , else , while и for . В такой ситуации под действие выражений попадает только первая инструкция макроса, и это, вероятно, ошибка:

-Wnonnull

Предупреждает о передаче нулевого указателя в функцию, аргументы которой помечены атрибутом nonnull .

-Wnonnull-compare

Предупреждает о сравнении с нулём аргумента функции, помеченного атрибутом nonnull .

-Wparentheses

Типичный случай — опечатались, и вместо равенства написали присвоение:

Компилятор, естественно, сомневается:

Либо исправляем код, либо убеждаем компилятор в том, что мы хотели именно присвоение:

-Wpessimizing-move

Иногда явная попытка переноса может ухудшить производительность. Пример:

-Wreorder

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

-Wreturn-type

Предупреждает о том, что из функции не вернули заявленный результат:

-Wsequence-point

Сообщает о подозрительных операциях относительно точек следования. Любимый пример (никогда так не делайте):

-Wsign-compare

Одно из важнейших предупреждений. Сообщает о сравнении знаковых и беззнаковых чисел, которое может произвести некорректный результат из-за неявных преобразований. К примеру, отрицательное знаковое число неявно приводится к беззнаковому и внезапно становится положительным:

-Wsizeof-pointer-div

Предупреждает о подозрительном делении друг на друга двух результатов выражения sizeof , когда размер указателя делится на размер объекта. Обычно это бывает, когда пытаются вычислить размер массива, но вместо массива по ошибке берут указатель:

-Wsizeof-pointer-memaccess

Предупреждает о подозрительных параметрах, передаваемых в строковые функции и функции для работы с памятью ( str. , mem. и т.п.), и использующих оператор sizeof . Например:

-Wstrict-aliasing

Каламбур типизации (strict aliasing) — это отдельная большая тема для разговора. Предлагаю читателю найти литературу по этой теме самостоятельно.

В общем, это тоже крайне полезное предупреждение.

-Wswitch

Предупреждает о том, что не все элементы перечисления задействованы в конструкции switch :

-Wtautological-compare

Предупреждает о бессмысленном сравнении переменной с самой собой:

Кроме того, сообщает о сравнениях при участии битовых операций, которые имеют всегда один и тот же результат (всегда истинно или всегда ложно):

-Wtrigraphs

Предупреждает о наличии триграфов, которые могут изменить смысл программы. Не сообщается о триграфах в теле комментария, за исключением случаев, когда триграф трактуется как перевод строки.

-Wuninitialized

Предупреждает об использовании переменных и членов класса, которые не были проинициализированы:

-Wunused-function

Предупреждает о том, что статическая функция объявлена, но не определена, либо о том, что статическая функция, не помеченная как inline , не используется.

-Wunused-variable

Предупреждает о том, что переменная не используется.

Для того, чтобы помочь компилятору понять, что так и задумывалось, можно использовать конструкцию static_cast (. ) :

«Агрегатор» дополнительных предупреждений. Включает много интересного, чего нет в -Wall (как и в случае с -Wall , рассмотрены будут не все возможности).

-Wempty-body

Предупреждает о пустом теле условных выражений или цикла do-while . Чаще всего это говорит об опечатке, меняющей логику программы:

-Wimplicit-fallthrough

Предупреждает о «проваливании» в операторе switch :

Компилятор предполагает, что программист забыл break , и case 2 не должен проваливаться:

В C++17 для обозначения явного намерения появился специальный атрибут — fallthrough :

-Wmissing-field-initializers

Предупреждает о том, что отдельные члены структуры не были проинициализированы. Скорее всего это просто забыли сделать:

-Wredundant-move

Предупреждает о ненужном вызове std::move в случаях, когда компилятор сам сделает всё, что нужно:

-Wtype-limits

Предупреждает о сравнениях, которые всегда имеют один и тот же результат. Например, когда беззнаковое число проверяется на неотрицательность. Если программист делает такую проверку, то, видимо, предполагает, что число в теории может быть отрицательным, однако, это не так. Видимо, он где-то ошибся:

-Wshift-negative-value

Предупреждает об операциях сдвига для отрицательных значений. Отрицательными могут быть только знаковые числа, а для них это некорректно:

-Wunused-parameter

Предупреждает о неиспользуемом параметре функции. Возможно, про него просто забыли, и в этом случае функция может работать некорректно.

В C++17 для явного выражения намерения существует атрибут maybe_unused :

-Wunused-but-set-parameter

Предупреждает о том, что в параметр функции было записано значение, но после этого он ни разу не использовался. Возможно, про него снова забыли:

-Wpedantic

-Wall и -Wextra — это не всё, на что способен компилятор.

В дополнение к ним существует флаг -Wpedantic (он же -pedantic ), который проверяет соответствие кода стандарту ISO C++, сообщает об использовании запрещённых расширений, о наличии лишних точек с запятой, нехватке переноса строки в конце файла и прочих полезных штуках.

Нужно больше предупреждений

Но и это ещё не всё. Есть несколько флагов, которые почему-то не входят ни в один из «аргегаторов», но крайне важны и полезны.

-Wctor-dtor-privacy

Предупреждает о том, что класс выглядит неиспользуемым, потому что конструкторы и деструкторы закрыты, а друзей и открытых статических функций-членов у него нет.

Аналогично, сообщает, что у класса есть закрытые функции-члены, а открытых нет ни одной.

-Wnon-virtual-dtor

Предупреждает о том, что у класса есть виртуальные функции-члены, но деструктор при этом не виртуальный. Очень сложно представить себе такой класс. Вероятнее всего, это ошибка.

-Wold-style-cast

Предупреждает о приведении типов в стиле языка C. В плюсах есть прекрасные и ужасные static_cast , dynamic_cast , reinterpret_cast и const_cast , которые более локальны и более описательны. Сишный способ слишком сильный и — о, ужас, — небезопасный. Лучше его не использовать вообще.

-Woverloaded-virtual

Предупреждает о попытке в классе-наследнике перегрузить виртуальную функцию базового класса:

-Wsign-promo

Крайне полезный флаг. Предупреждает о неочевидном выборе перегруженной функции:

Вероятнее всего, хотели-таки позвать вторую перегрузку, а не первую. А если всё-таки первую, то будьте любезны сказать об этом явно.

-Wduplicated-branches

Предупреждает о том, что ветви if и else одинаковы:

Условный оператор ?: также под прицелом:

Для меня абсолютная загадка, почему этот флаг не включён не то, что в -Wall , а вообще по умолчанию.

-Wduplicated-cond

Предупреждает об одинаковых условиях в цепочках if-else-if :

-Wfloat-equal

Предупреждает о проверке на равенство между двумя числами с плавающей точкой. Скорее всего, это ошибка, и сравнение нужно проводить с заданной точностью.

Если же требуется именно сравнить на равенство (такое редко, но бывает), то можно использовать std::equal_to , который под предупреждение не попадает.

-Wshadow=compatible-local

Полезная опция, которая не даёт перекрыть локальную переменную другой локальной переменной при условии, что они имеют совместимые типы.

-Wcast-qual

Предупреждает о преобразовании указателя, при котором сбрасываются квалификаторы. Например, чтобы случайно не потерять const .

-Wconversion

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

Если вы раньше никогда не включали этот флаг, то будет интересно.

-Wzero-as-null-pointer-constant

Предупреждает об использовании целочисленного нуля вместо nullptr .

Флаг для педантов. Сообщает о лишней точке с запятой после определения функции-члена.

-Wsign-conversion

Как и -Wconversion помогает предотвратить большое количество неявных преобразований, которые запросто могут быть ошибками:

-Wlogical-op

Предупреждает о подозрительных логических выражениях. Например, когда вместо побитового «И» поставили логическое «И», или логическое выражение имеет одинаковые операнды:

-Werror

С этого, вообще говоря, стоило бы начать. Данный флаг делает все предупреждения ошибками. Код не скомпилируется при наличии хотя бы одного предупреждения.

Без этого флага всё остальное имеет мало смысла. Но если понять и принять мысль о том, что предупреждение — это что-то подозрительное, и их быть не должно, то именно этот флаг и позволит поддерживать код в чистоте.

В дополнение к -Werror существует флаг -pedantic-errors , который не эквивалентен комбинации -Wpedantic -Werror .

Заключение

Резюмируя, для компилятора GCC (Clang кое-что из этого не умеет, к сожалению) я рекомендую включать следующий минимальный набор флагов, по необходимости дополняя его более сложными диагностиками.

Да, такой список флагов может породить большое количество ошибок, которые поначалу могут показаться излишними. Но явное лучше неявного. Если знаешь, что делаешь — делай. Но делай это так, чтобы всем было понятно, что именно так ты и хотел. Поработав таким образом хотя бы неделю, вы поймёте, насколько это прекрасно, и уже не сможете вернуться обратно.

Любите ваш компилятор и помогайте ему помогать вам писать программы.

Источник

Hi,

I’m programming a lua-to-c++ library, but more for myself and fun. In it I work a lot with partial template specializations and non-type template arguments.

Right now I get an error msg like «test.cpp:51: error: address of overloaded function with no contextual type information». Maybe somebody could help me on unterstanding why the code fails.

At the end you find a copy&compileable stripped down version of my code.

I would really appreciate any help or ideas :)


#include <iostream>
#include <vector>

using namespace std;
typedef vector<int> vec;
typedef vec::reference tref;
typedef vec::size_type tsize;

template<typename T, T* P>
struct FunWrapper {
};

template<typename T, T P>
struct MemFunWrapper {
};

template<typename tRet,typename A1,tRet (*func)(A1)>
struct FunWrapper<tRet(A1),func> {
  static void foo() { cout<<"Fun Wrap"<<endl; }
};

template<class C,typename tRet,typename A1,tRet (C::*memFunc)(A1)>
struct MemFunWrapper<tRet(C::*)(A1),memFunc>{
  static void foo() { cout<<"Mem Fun Wrap"<<endl; }
};

template<typename T,T* P>
void reg() {
  FunWrapper<T,P>::foo();
}

template<typename T,T P>
void reg() {
  MemFunWrapper<T,P>::foo();
}

template<typename T,T P>
void reg_mf() {
  MemFunWrapper<T,P>::foo();
}

int main() {
  /* on gcc 4.1.1 the following line gives me                                                                                                                      
     test.cpp:51: error: address of overloaded function with no contextual type information                                                                        
                                                                                                                                                                   
     if you comment out the FunWrapper<tRet(A1),func> specialization it works as well                                                                              
  */
  //reg<tref(vec::*)(tsize),&vec::at>();                                                                                                                           

  /* this version works */
  reg_mf<tref(vec::*)(tsize),&vec::at>();
  return 0;
}

vec::at() is actually two different functions const int & vec::at(size_type) const and int & vec::at(size_type). What the error message is telling you is that it can’t figure out which one you mean. You can disambiguate it with a cast.

Sorry, but I don’t understand what you mean.

Even though I know it wouldn’t work I tried:

 reg<tref(vec::*)(tsize),static_cast<tref(vec::*)(tsize)>(vec::at)>(); 

One cannot cast something in the template parameter list. More specifically my compiler complains «a cast to a type other than an integral or enumeration type cannot appear in a constant-expression».

But this wasn’t probably what you meant by casting. Also it’s weird that if I comment the one specialization out (see the source), the compiler doesn’t complain. Even though the specialization wasn’t for member function pointers but for normal function pointers.

Could you please be a little bit more verbose?

I’ve redone my example code and I narrowed down the problem. Probably I get some more responses now :)

/* takes function type as first template parameter    *//* and a function pointer of the function type as     *//* the second template parameter                      */template<typename T,T* P>void reg() { }/* takes member function type as first template       *//* parameter and member function pointer of the type  *//* as second template parameter                       */template<typename T,T P>void reg() { }template<typename T,T P>void reg_mf() { }struct T_at_atconst {  int at(int) { }  const int at(int) const { }};int main() {  /* the compiler only can't cope with the normal and    */  /* the const version of the member function            */  /* if there are two versions of the template function  */  /* one which accepts function pointers and one which   */  /* accepts member function pointers                    */  /* but actually the memFun type should be clear since  */  /* I have to give as the first template parameter      */  /* so this works and the compiler can deduce which     */  /* version of the member function should be used       */  reg_mf<int(T_at_atconst::*)(int),&T_at_atconst::at>();  reg_mf<const int(T_at_atconst::*)(int)const,&T_at_atconst::at>();  /* but this won't work, why?                           */  //reg<int(T_at_atconst::*)(int),&T_at_atconst::at>();                           //reg<const int(T_at_atconst::*)(int)const,&T_at_atconst::at>();                return 0;}

I cannot explain this odd behaviour. Maybe somebody can explain. Maybe it’s explained in the standard or it’s just a flaw of my compiler.

Thanks in advance :)

Понравилась статья? Поделить с друзьями:
  • Error penumerator getdefaultaudioendpoint
  • Error outputting keys and certificates openssl
  • Error output so disabling automatic redirect
  • Error output processing capture one
  • Error out of video memory trying to allocate a texture pubg