What does this error message mean?
error: call of overloaded ‘setval(int)’ is ambiguous
huge.cpp:18: note: candidates are: void huge::setval(unsigned int)
huge.cpp:28: note: void huge::setval(const char*)
My code looks like this:
#include <iostream>
#define BYTES 8
using namespace std ;
class huge {
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
void setval(const char *);
};
void huge::setval(unsigned int t) {
for(int i = 0; i< BYTES ; i++) {
data[i] = t;
t = t >> 1;
}
}
void huge::setval(const char *s) {
for(int i = 0; i< BYTES ; i++)
data[i] = s[i];
}
int main() {
huge p;
p.setval(0);
return 0;
}
NathanOliver
171k28 gold badges283 silver badges397 bronze badges
asked Jan 12, 2011 at 17:54
3
The literal 0
has two meanings in C++.
On the one hand, it is an integer with the value 0.
On the other hand, it is a null-pointer constant.
As your setval
function can accept either an int
or a char*
, the compiler can not decide which overload you meant.
The easiest solution is to just cast the 0
to the right type.
Another option is to ensure the int
overload is preferred, for example by making the other one a template:
class huge
{
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
template <class T> void setval(const T *); // not implemented
template <> void setval(const char*);
};
answered Jan 12, 2011 at 19:47
6
The solution is very simple if we consider the type of the constant value, which should be «unsigned int» instead of «int».
Instead of:
setval(0)
Use:
setval(0u)
The suffix «u» tell the compiler this is a unsigned integer. Then, no conversion would be needed, and the call will be unambiguous.
answered Nov 28, 2011 at 14:27
Leonardo L.Leonardo L.
3062 silver badges5 bronze badges
1
replace p.setval(0);
with the following.
const unsigned int param = 0;
p.setval(param);
That way it knows for sure which type the constant 0 is.
answered Jan 12, 2011 at 17:58
Null SetNull Set
5,37224 silver badges37 bronze badges
Use
p.setval(static_cast<const char *>(0));
or
p.setval(static_cast<unsigned int>(0));
As indicated by the error, the type of 0
is int
. This can just as easily be cast to an unsigned int
or a const char *
. By making the cast manually, you are telling the compiler which overload you want.
answered Jan 12, 2011 at 17:58
EclipseEclipse
44.6k20 gold badges112 silver badges170 bronze badges
Cast the value so the compiler knows which function to call:
p.setval(static_cast<const char *>( 0 ));
Note, that you have a segmentation fault in your code after you get it to compile (depending on which function you really wanted to call).
answered Jan 12, 2011 at 17:58
Mark LoeserMark Loeser
17.5k2 gold badges26 silver badges34 bronze badges
That is ambiguous because a pointer is just an address, so an int
can also be treated as a pointer – 0 (an int
) can be converted to unsigned int
or char *
equally easily.
The short answer is to call p.setval()
with something that’s unambiguously one of the types it’s implemented for: unsigned int
or char *
. p.setval(0U)
, p.setval((unsigned int)0)
, and p.setval((char *)0)
will all compile.
It’s generally a good idea to stay out of this situation in the first place, though, by not defining overloaded functions with such similar types.
Adrian Mole
49.5k155 gold badges49 silver badges79 bronze badges
answered Jan 12, 2011 at 18:00
metamattmetamatt
13.7k7 gold badges46 silver badges56 bronze badges
2
Offline
Зарегистрирован: 26.05.2016
Только начал программировать. Пока написал только вот это.
const int buttonPin = 2; // номер входа, подключенный к кнопке //задаём переменные int buttonState = 0; // переменная для хранения состояния кнопки int a = 11; // переменная word Inputs[8]; // массив, в котором будут храниться данные из 8 байт void setup() { Serial.begin(9600); // открывает последовательный порт, устанавливает скорость 9600 бит/c Serial.write(Inputs[0], 8); } void loop() { }
Компилятор указывает на строку Serial.write и пишет «call of overloaded ‘write(word&, int)’ is ambiguous».
Если убрать из скобок размер массива, и написать Serial.write(Inputs[0]); то компилятор это съедает. Но хотелось бы понять как передавать массив байтов.
Problem
Suppose you have a JsonDocument
, named doc
, and you want to print the value "myValue"
.
If you do this:
Serial.println(doc["myValue"]);
you’ll get the following compilation error:
call of overloaded 'println(ArduinoJson6101_00000::enable_if<true, ArduinoJson6101_00000::MemberProxy<ArduinoJson6101_00000::JsonDocument&, const char*> >::type)' is ambiguous
Quite scary, right?
Explanation
It’s not that complicated. The compiler tells us that we passed some obscure type to Serial.println()
and that he didn’t know which overload of println()
to choose.
What’s an overload, you ask? When the same function has several versions with different parameters, we call each version an “overload.” In our case, Serial.println()
has 12 overloads:
size_t println(const __FlashStringHelper *);
size_t println(const String &s);
size_t println(const char[]);
size_t println(char);
size_t println(unsigned char, int = DEC);
size_t println(int, int = DEC);
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(double, int = 2);
size_t println(const Printable&);
size_t println(void);
As you can see, there is no overload for JsonVariant
, so how can the compiler decide which one to use?
Solution
There are two ways to solve the ambiguity:
- You can explicitly cast the
JsonVariant
to type supported byprintln()
- You can avoid
println()
The first solution only works if you know the type of the value. For example, if you know that "myValue"
contains an integer, you can write:
Serial.println(doc["myValue"].as<int>());
However, if you don’t know the type, you must use the second solution: replace println()
with serializeJson()
:
serializeJson(doc["myValue"], Serial);
What about Printable
?
As you saw above, println()
has an overload that takes a Printable
, an interface that allows supporting custom types. If JsonVariant
implemented Printable
, the call to println()
would not be ambiguous. So why ArduinoJson doesn’t do that?
Unfortunately, implementing Printable
makes the code of the library significantly bigger, and having a small footprint is one of the primary goals of ArduinoJson. Early versions supported Printable
, but this feature was removed because it was not worth the extra bytes.
Заголовок <math.h>
является заголовком C std lib. Он определяет много вещей в глобальном пространстве имен. Заголовок <cmath>
— это С++-версия этого заголовка. Он определяет по существу тот же самый материал в пространстве имен std
. (Есть некоторые отличия, например, версия С++ поставляется с перегрузками некоторых функций, но это не имеет значения.) Заголовок <cmath.h>
не существует.
Поскольку поставщики не хотят поддерживать две версии того, что по сути является одним и тем же заголовком, они придумали разные возможности, чтобы иметь только одну из них за кулисами. Часто, что заголовок C (поскольку компилятор С++ способен разобрать это, в то время как противоположное не будет работать), а заголовок С++ включает это и вытаскивает все в пространство имен std
. Или есть макрос магии для разбора одного и того же заголовка с или без namespace std
, обернутых вокруг него или нет. Для этого добавьте, что в некоторых средах это неудобно, если заголовки не имеют расширения файла (например, редакторы не могут выделить код и т.д.). Таким образом, некоторые поставщики имели бы <cmath>
как однострочный, включая другой заголовок с расширением .h
. Или некоторые из них будут отображать все, включая сопоставление <cblah>
с <blah.h>
(которое с помощью макроса становится заголовком С++, когда __cplusplus
определено и в противном случае становится заголовком C) или <cblah.h>
или что-то еще.
По этой причине на некоторых платформах, включая такие, как <cmath.h>
, которые не должны существовать, изначально удастся, хотя это может привести к тому, что компилятор не будет эффектно позже.
Я не знаю, какую версию std lib вы используете. Я предполагаю, что это тот, который поставляется с GCC, но этого я не знаю, поэтому я не могу точно объяснить, что произошло в вашем случае. Но это, безусловно, сочетание одного из вышеупомянутых хакеров, связанных с продавцом, и вы включаете заголовок, который вы не должны были включать в себя. Возможно, это тот, где <cmath>
отображается на <cmath.h>
с определенным (набором) макросов, которые вы не определили, так что вы оказались с обоими определениями.
Обратите внимание, что этот код еще не должен компилироваться:
#include <cmath>
double f(double d)
{
return abs(d);
}
В глобальном пространстве имен не должно быть abs()
(it std::abs()
). Однако в соответствии с описанными выше трюками реализации вполне может быть. Портирование такого кода позже (или просто попытка скомпилировать его с вашей следующей версией поставщика, что не позволяет этого) может быть очень утомительным, поэтому вам следует следить за этим.
abstract declarator ‘TYPE’ used as declaration[edit | edit source]
- Message found in GCC version 4.5.1
- often grouped together with:
- member ‘DATA_MEMBER’ with constructor not allowed in anonymous aggregate
- member ‘DATA_MEMBER’ with destructor not allowed in anonymous aggregate
- member ‘DATA_MEMBER’ with copy assignment operator not allowed in anonymous aggregate
- often grouped together with:
- a class or struct is missing a name:
struct { // error, no name int bar; };
- a header file has a class or struct with a name already used inside ifndef, define statements
#ifndef foo #define foo #include <vector> struct foo { // error, foo already in use std::vector<int> bar; }; #endif
call of overloaded ‘FUNCTION’ is ambiguous[edit | edit source]
‘VARIABLE’ cannot appear in a constant-expression[edit | edit source]
‘VARIABLE’ cannot be used as a function[edit | edit source]
- Message found in GCC version 4.5.1
- make sure the variable name does not have an underscore in it (compiler weirdness)
- you’re using the same name for a variable name and a function inside a function definition
int foo(int baf) { return baf; } int bar(int foo) { foo = foo(4); return foo; }
conversion from ‘TYPE’ to non-scalar type ‘TYPE’ requested[edit | edit source]
- Message found in GCC version 4.5.1
- type conversion error, look for missing «::» syntax or missing parenthesis
- possibly a casting error
- a class member function returns a value that does not match the function’s declared return type
class Foo { public: int x; }; class Bar { public: Foo Maz() { return 0; } // 0 is of type int, not Foo };
could not convert ‘STATEMENT’ to ‘bool’[edit | edit source]
- Message found in GCC versions 3.2.3, 4.5.1
- you a mistyped comparison operator (e.g., using: «=» instead of «==»)
- you used an incorrect return type for the called function’s definition
// you had: foo operator<(const foo & f) const // instead of: bool operator<(const foo & f) const
- you’re using an invalid argument for a conditional statement
string x = "foo"; if (x) cout << "true" << endl;
declaration of ‘FUNCTION’ outside of class is not definition[edit | edit source]
- Message found in GCC versions 3.2.3, 4.5.1
- try using ‘=’ to initialize a value instead of parenthesis
- you used a semicolon or comma between a constructor and an initializer list instead of a colon
- you left a semicolon before the body of a function definition
class Foo { public: int bar; Foo(int x); }; Foo::Foo(int x); // semicolon ';' needs to be removed { bar = x; }
declaration of ‘VARIABLE’ shadows a parameter[edit | edit source]
- Message found in GCC versions 3.2.3, 4.5.1
- you’re redefining a variable name that’s already in use, possibly declared in the function’s parameter list
int foo(int bar) { int bar; return bar; }
‘TYPE’ does not name a type[edit | edit source]
- Message found in GCC version 4.5.1
- in GCC version 3.2.3 sometimes reported as: syntax error before ‘CHARACTER’ token
- in GCC version 4.0.1, sometimes reported as: ISO C++ forbids declaration
- e.g.: ISO C++ forbids declaration of ‘vector’ with no type
- you left out an object’s name qualifier or using directive
ostream & os; // instead of: std::ostream & os;
- make sure you didn’t mistype the scope operator «::», e.g.: «name:name» instead of «name::name»
- make sure you included the required libraries
#include <iostream> // missing vector library include class Foo { public: std::vector<int> Bar(std::vector<int> FooBar) { return FooBar; } };
- a header file is listed after a file that makes use of it in the include directives
// test.h file #ifndef TEST_H_ #define TEST_H_ std::string bar; #endif // test.cpp file #include "test.h" #include <iostream> // error, needed before test.h using namespace std; int main() { cout << bar << endl; return 0; }
expected ‘TOKEN’ before ‘TOKEN’ token[edit | edit source]
- Message found in GCC versions 3.2.3, 4.5.1
- in GCC version 3.2.3 sometimes reported as: syntax error before ‘CHARACTER’ token
- check for a missing comma or parenthesis in a function’s parameters
- check for a missing semicolon
- e.g.: expected ‘,’ or ‘;’ before ‘TOKEN’
const int MAX = 10 // error int main() { string foo; cout << foo.size(); return 0; }
- possibly from a double namespace definition, or a fully-qualified (e.g., std::cout) name already under a ‘using’ directive
- possible missing ‘<<‘ or ‘>>’ operator in a cin/cout statement
int foo = 0, bar = 0; cin foo >> bar; // should be: cin >> foo >> bar;
expected primary-expression before ‘TOKEN’[edit | edit source]
- expected primary-expression before ‘int’
- Message found in GCC version 4.5.1
- in GCC version 3.2.3 reported as: parse error before ‘)’ token
- one likely cause is using (or leaving in) a type name in a function call
int sum(int x, int y) { return (x + y); } int main() { int a = 4, b = 5; sum(a, int b); // int is the problem causer return 0; }
expected unqualified-id before[edit | edit source]
- Message found in GCC version 4.5.1
- check your syntax for missing, misplaced, or erroneous characters
- expected unqualified-id before ‘(‘ token
- e.g.: parentheses in a class name
class Foo() { public: int x; };
- expected unqualified-id before ‘return’
- e.g.: missing opening brace in a conditional statement
int foo = 3, bar = 2; if (foo > bar) // error, no "{" cout << foo << endl; }
incompatible types in assignment of ‘TYPE’ to ‘TYPE’[edit | edit source]
- Message found in GCC versions 4.5.1
- you’re trying to assign to or initialize a character array using a character pointer
- e.g.: incompatible types in assignment of ‘const char*’ to ‘char [10]’
char bar[10]; const char *foo = "ppp"; bar = *foo; // error // possible fix, use strcpy from the cstring header: char bar[10]; const char *foo = "ppp"; strcpy(bar, foo);
- improperly accessing elements of a 2D array
char foo[2][3]; foo[1] = ' '; // error, need both dimensions, eg: foo[1][0] = ' ';
invalid conversion from ‘TYPE’ to ‘TYPE’[edit | edit source]
- Message found in GCC versions 3.2.3, 4.5.1
- make sure parentheses were not left out of a function name
- make sure you are passing a function the correct arguments
char foo = 'f'; char bar[] = "bar"; if (strcmp(foo, bar) != 0) cout << "Correct answer!"; // strcmp was expecting 2 character pointers, foo doesn't qualify
invalid operands of types ‘TYPE’ and ‘TYPE’ to binary ‘FUNCTION’[edit | edit source]
- Message found in GCC version 4.5.1
- You’re trying to concatenate to C string arguments with the addition operator
// attempting to combine two C-strings cout << "abc" + "def"; // possible fix: convert 1 argument to a string type cout << "abc" + string("def");
invalid use of template-name[edit | edit source]
- invalid use of template-name ‘TEMPLATE’ without an argument list
- Message found in GCC version 4.5.1
- often paired with: expected unqualified-id before ‘TOKEN’
- in GCC version 3.2.3 reported as: syntax error before ‘CHARACTER’ token
- the type is missing after the class name in a function definition
template <class T> class Foo { private: int x; public: Foo(); }; template<class T> Foo::Foo() { x = 0; } // error, should be: Foo<T>::Foo()
is not a member of[edit | edit source]
- Message found in GCC versions 4.5.1
- check for a missing header include
- example: ‘cout’ is not a member of ‘std’
// test.cpp // file is missing iostream include directive int main() { std::cout << "hello, world!n"; return 0; }
‘TYPE’ is not a type[edit | edit source]
- Message found in GCC version 4.5.1
- in GCC version 3.2.3 reported as: type specifier omitted for parameter ‘PARAMETER’
- you mistyped a template parameter in a function declaration
void foo(int x, vector y);
- an included header file does not have the correct libraries included in the source file to implement it:
- e.g.: you’re using #include «bar.h» without including the «foo.h» that «bar.h» needs to work
- Check that there are no methods with the same name as ‘TYPE’.
‘CLASS_MEMBER’ is private within this context[edit | edit source]
- Message found in GCC versions 3.2.3, 4.5.1
- usually reported in the format:
- (LOCATION_OF_PRIVATE_DATA_MEMBER) error: ‘DATA_MEMBER’ is private
- (LOCATION_OF_CODE_ACCESSING_PRIVATE_DATA) error: within this context
- Message usually results from trying to access a private data member of a class or struct outside that class’s or struct’s definition
- Make sure a friend member function name is not misspelled
class FooBar { private: int bar; public: friend void foo(FooBar & f); }; void fooo(FooBar & f) { // error f.bar = 0; }
- make sure a read only function is using a ‘const’ argument type for the class
- make sure functions that alter data members are not const
- check for derived class constructors implicitly accessing private members of base classes
class Foo { private: Foo() {} public: Foo(int Num) {} }; class Bar : public Foo { public: Bar() {} // Bar() implicitly accesses Foo's private constructor };
- solution 1: use an initializer list to bypass implicit initialization
- solution 2: make the accessed base class member protected instead of private
- You’re trying to initialize a contained class member by accessing private data
class Foo { private: char mrStr[5]; public: Foo(const char *s = "blah") { strcpy(mrStr, s); } }; class Bar { private: int mrNum; Foo aFoo; public: Bar(int n, const Foo &f); }; // error, attempting to use the Foo class constructor by accessing private data: Bar::Bar(int n, const Foo &f) : aFoo(f.mrStr) { // mrStr is private mrNum = n; }
possible fix, assign the whole object rather than part of it:
Bar::Bar(int n, const Foo &f) : aFoo(f) { mrNum = n; }
ISO C++ forbids declaration of ‘FUNCTION’ with no type[edit | edit source]
- Message found in GCC version 3.2.3, 4.5.1
- you’ve created a function with no listed return type
Foo() { return 0: } // should be: int Foo() { return 0: }
multiple definitions of[edit | edit source]
- eg: multiple definition of `main’
- Message found in GCC version 4.5.1
- check for missing inclusion guard in header file
- check for duplicate file listing in compile commands / makefile
- e.g.: g++ -o foo foo.cpp foo.cpp
- check for definitions rather than only declarations in the header file
‘CLASS FUNCTION(ARGUMENTS)’ must have an argument of class or enumerated type[edit | edit source]
- Message found in GCC versions 3.2.3, 4.5.1
- you’re attempting to access members of a class with a non-member function
- non-member functions must access class members explicitly
- eg: CLASS_NAME FUNCTION_NAME(CLASS_NAME OBJECT_NAME, ARGUMENTS)
- you’re redefining an operator for a standard (built-in) type
class Foo { public: friend int operator+(int x, int y); };
new types may not be defined in a return type[edit | edit source]
- Message found in GCC version 4.5.1
- in GCC version 3.2.3, reported as:
-
- semicolon missing after definition of ‘CLASS’
- ISO C++ forbids defining types within return type
- check for a missing semicolon at the end of a class definition
class Foo { public: int x; } // Error
no match for call to ‘FUNCTION’[edit | edit source]
- Message found in GCC versions 3.2.3, 4.5.1
- make sure the function’s namespace is used ( using namespace std / std::function() )
- make sure the function name is not misspelled, parentheses aren’t missing
- make sure the function is called with the correct arguments / types / class
- if you’re initializing a variable via parentheses, if there’s underscores in the variable name try removing them. Sometimes an equals sign is the only way…
- you’re using the same name for a variable and a function within the same namespace
string bar() { string foo = "blah"; return foo; } int main() { string bar; bar = bar(); // error, "bar()" was hidden by string initialization return 0; }
no matching function for call to ‘FUNCTION’[edit | edit source]
- Message found in GCC version 4.5.1
- make sure there aren’t parentheses where there shouldn’t be (e.g.: classname::value() instead of classname::value )
- you’re using a string argument with a function that expects a C-string
// broken code ifstream in; string MrString = "file.txt"; in.open(MrString); // solution: convert the string to a C-string ifstream in; string MrString = "file.txt"; in.open(MrString.c_str());
non-constant ‘VARIABLE’ cannot be used as template argument[edit | edit source]
- Message found in GCC version 3.2.3
- in GCC version 4.5.1 reported as: ‘VARIABLE’ cannot appear in a constant-expression
- variable used for a template argument, which are required to be constant at compile time
template <class T, int num> class Bar { private: T Foo[num]; }; int main() { int woz = 8; Bar<double, woz> Zed; // error, woz is not a constant return 0; }
non-member function ‘FUNCTION’ cannot have cv-qualifier[edit | edit source]
- error: non-member function ‘int Foo()’ cannot have cv-qualifier
- cv = constant / volatile
- Message found in GCC version 4.5.1
- you’re using the ‘post’ const (constant value) on a non-member function
- you’re not using the scope qualifier («TYPENAME::») in the function definition
- you mistyped the definition for a template class’s member function
template<class Type> class Foo { private: int stuff; public: int bar() const; }; template<class Type> int Foo::bar() const { // error return stuff; }
possible fix:
template<class Type> int Foo<Type>::bar() const { return stuff; }
passing ‘const OBJECT’ as ‘this’ argument of ‘FUNCTION’ discards qualifiers[edit | edit source]
- Message found in GCC version 4.5.1
- you’re returning an address
- you’re attempting to access a container element with a const_iterator using a member function that has no non-const versions. The non-const function does not guarantee it will not alter the data
request for member ‘NAME’ in ‘NAME’, which is of non-class type ‘CLASS’[edit | edit source]
- Message found in GCC versions 4.5.1
- in GCC version 3.2.3 reported as:
-
- request for member ‘NAME’ in ‘NAME’, which is of non-aggregate type ‘TYPE’
- check the function call in the code, it might be calling a function with incorrect arguments or it might have misplaced/missing parenthesis
- your using the «*this» pointer where you should just be using the functions name
- e.g., use: return mem_func(); instead of: return *this.mem_func();
- using the «*this» pointer with the wrong syntax
class Foo { public: int x; Foo(int num = 0) { x = num; } void newX(int num); }; void Foo::newX(int num) { *this.newX(num); // error, need (*this).newX or this->newX }
statement cannot resolve address of overloaded function[edit | edit source]
- Message found in GCC versions 3.2.3, 4.5.1
- make sure you’re not forgetting the parenthesis after a member function name
class Foo { public: int Bar() { return 0; } }; int main() { Foo x; x.Bar; // error return 0; }
two or more data types in declaration of ‘NAME’[edit | edit source]
- Message found in GCC version 4.5.1
- in GCC version 3.2.3 reported as: extraneous ‘TYPE’ ignored
- you have multiple data types listed for a function declaration’s return value
int char sum(int x, int y); // int char
- possibly a missing semicolon in between 2 type declarations
- usually missing in a function, struct, or class declaration after the curly braces {}
<GOBBLEDEGOOK> undefined reference to <GOBBLEDEGOOK>[edit | edit source]
- Message found in GCC version 4.5.1
- in GCC versions 4.0.1, 4.2.1 reported as: Undefined symbols
- check for a missing or mistyped header includes
- check for a missing or mistyped files/libraries in a project/make file
- check for a missing, mistyped, or undefined functions or class constructors
// header file void foo(); void bar(); void baz(); // implementation file, bar definition is missing void foo() { cout << "foon"; } void baz() { cout << "bazn"; }
- check for function declarations that do not match their definitions
- make sure function names do not overlap those in existing header files
- make sure compile commands syntax / makefile structure is correct (e.g.: g++ -o file.cc … etc.)
- no main() function is defined in any of the files inside a project/makefile
- e.g.: undefined reference to `WinMain@16′
‘NAME’ was not declared in this scope[edit | edit source]
- Message found in GCC version 4.5.1
- in GCC versions 3.2.3 reported as: ‘FUNCTION’ undeclared (first use of this function)
- look for a misspelled or changed variable/function/header call name
lonh wait; // instead of: long wait;
- make sure the proper header and library files are included
- defined variables may need the headers they utilize included in all files that use the defined variables