There is sample
// Example 2: Will this compile?
//
// In some library header:
namespace N { class C {}; }
int operator+(int i, N::C) { return i+1; }
// A mainline to exercise it:
#include <numeric>
int main()
{
N::C a[10];
std::accumulate(a, a+10, 0);
}
From "Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions" -- Item 34. Name Lookup and the Interface Principle—Part 4
g++ 5.4 compiles it successfully.
But adding #include <iostream> breaks the code
// Example 2: Will this compile?
//
// In some library header:
namespace N { class C {}; }
int operator+(int i, N::C) { return i+1; }
// A mainline to exercise it:
#include <numeric>
#include <iostream>
int main()
{
N::C a[10];
std::accumulate(a, a+10, 0);
}
clang-4.0 is able to compile it. g++ 5.4 and g++7.2.0 show he following error
In file included from /usr/include/c++/7/numeric:62:0,
from src/widget.cpp:7:
/usr/include/c++/7/bits/stl_numeric.h: In instantiation of ‘_Tp std::accumulate(_InputIterator, _InputIterator, _Tp) [with _InputIterator = N::C*; _Tp = int]’:
src/widget.cpp:12:35: required from here
/usr/include/c++/7/bits/stl_numeric.h:127:18: error: no match for ‘operator+’ (operand types are ‘int’ and ‘N::C’)
__init = __init + *__first;
~~~~~~~^~~~~~~~~~
Looks like bug in g++. I'm interested to know if workaround exists?
IF somebody as curios as me - I'm posting what I have understood from further reading in the book.
Compiler will look for operator+ called from std::accumulate starting with namespace std.
Only if no candidates found in the namespace - it will go up and look for global namespace candidates.
So original sample and modified sample in clang were compiled by pure luck that no operator+ was declared before std::accumulate.
As soon as new header was added to the game - compiler stopped to look into the global namespace and stopped seeing proper operator as candidate at all.
Best match was not so good and cause all this strange error messages.
Now moving operator+ into namespace N was initiating Koenig lookup - if one of the function arguments is in the namespace N - suitable candidates should be looked in this namespace as well as addition to regular lookup.
Related
I declare a namespace MYTIME in mytime.h file.
#include<ostream>
#ifndef _TIME_H
#define _TIME_H
namespace MYTIME{
class time
{
...
};
}
#endif
And try to use it in my time.cpp file,
#include"mytime.h"
#include<iostream>
using namespace std;
using namespace MYTIME;
time::time()
{
years = days = hours = minutes = 0;
seconds = 0;
months = JAN;
}
when I use g++ time.cpp to compile, errors are as follows
time.cpp:8:17: error: ‘MYTIME’ is not a namespace-name
using namespace MYTIME;
^~~~~~
time.cpp:8:23: error: expected namespace-name before ‘;’ token
using namespace MYTIME;
^
time.cpp:10:1: error: ‘time’ does not name a type
time::time()
time.cpp:31:6: error: ‘time’ is not a class, namespace, or enumeration
void time::addSec(long int s)
time.cpp: In function ‘void addSec(long int)’:
time.cpp:34:7: error: ‘seconds’ was not declared in this scope
m = (seconds + s) / 60;
^~~~~~~
time.cpp:34:7: note: suggested alternative: ‘useconds_t’
m = (seconds + s) / 60;
^~~~~~~
useconds_t
... // many same errors
where am i going wrong? and how to fix it? Looking for help.
Your header guard is using a name that is already defined. As a result, your namespace and class is never declared.
A simple test demonstrates the problem:
#include <iostream>
int main()
{
#ifdef _TIME_H
std::cout << "Well, well, well...\n";
#endif
}
You would expect this program to have no output, but when compiled with g++ and run, this program outputs:
Well, well, well...
To solve this, you should use more uniquely named headers, and don't attempt to use naming conventions employed by the standard library. In particular, prefixing with an underscore is generally not a good idea.
If your compiler supports #pragma once you may wish to consider using that instead.
I can't understand why I have this error, apparently the isalpha function is redeclared twice (my editor marks me: "2 more overloads") but I don't understand why, this is my code:
#include <iostream>
#include <set>
#include <algorithm>
#include <ctype.h>
#include <string>
using namespace std;
int main(){
cin.tie(nullptr);ios_base::sync_with_stdio(false);
string line;
string::iterator prev, act;
while(cin>>line){
// act = find_if(line.begin(), line.end(), [](int x) {return isalpha(x);}); // GOOD
act = find_if(line.begin(), line.end(), isalpha); // ERROR
cout<<*act<<endl;
}
}
I use g++ (MinGW.org GCC-6.3.0-1) 6.3.0
Error:
1215.cpp: In function 'int main()':
1215.cpp:14:56: error: no matching function for call to 'find_if(std::__cxx11::basic_string<char>::iterator, std::__cxx11::basic_string<char>::iterator, <unresolved overloaded function type>)'
act = find_if(line.begin(), line.end(), isalpha); // ERROR
^
In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\algorithm:62:0,
from 1215.cpp:3:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:3808:5: note: candidate: template<class _IIter, class _Predicate> _IIter std::find_if(_IIter, _IIter, _Predicate)
find_if(_InputIterator __first, _InputIterator __last,
^~~~~~~
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:3808:5: note: template argument deduction/substitution failed:
1215.cpp:14:56: note: couldn't deduce template parameter '_Predicate'
act = find_if(line.begin(), line.end(), isalpha); // ERROR
Note: if I don't use the "using namespace std" the code compiles and executes correctly.
Thanks in advance for any answers or advice
This is what might be happening.
There's an isalpha() in the <cctype> header under the std namespace and another isalpha() in the <locale> header under the very same std namespace. using namespace std pulls both into the your scope and thus the ambiguity while deducing the template.
Moral of the story: Avoid using using namespace std.
I can't understand why I have this error, apparently the isalpha function is redeclared twice (my editor marks me: "2 more overloads") but I don't understand why
Two overloads are declared, because the standard says that there are two overloads.
A good solution is to use a lambda, as you did in the comment. Unlike creating a function pointer, calling the function in the lambda allows the call to be resolved to the correct overload based on the passed arguments.
Your lambda should be improved though: Change the type of the parameter to unsigned char. This is needed because char may be a signed type, and if the value of a char is negative, then it will have a value outside the range of unsigned char, and passing a value outside the range of unsigned char into islpha will result in undefined behaviour. Fixed example:
auto isalpha = [](unsigned char c){
return std::isalpha(c);
};
act = find_if(line.begin(), line.end(), isalpha);
Also, remove the line using namespace std.
To complete # Zoso's answer:
Inside <iostream> are included <cctype> and locale_facets.h both define different std::isalpha functions .
Also, inside <cctype> includes <ctype.h> (which is in fact explicitly included in the example) and <ctype.h> defines an isalpha function (without the std namespace).
So one way to solve the problem is to call the isalpha function of<ctype.h>, for this it is necessary to exit the current namespace (std) with :: operator.
This code works:
#include <iostream>
#include <algorithm>
#include <ctype.h>
#include <string>
using namespace std;
int main(){
cin.tie(nullptr);ios_base::sync_with_stdio(false);
string line;
string::iterator prev, act;
while(cin>>line){
act = find_if(line.begin(), line.end(), ::isalpha);
cout<<*act<<endl;
}
}
Actually this code works fine in "DEV C++", but when I put it into my "Hacker-Rank" panel it gives this error "reference to function is ambiguous", although all the online compilers are giving errors...
I don't think here function overloading is somewhere interrupting, because this error mostly comes in function overloading.
#include <bits/stdc++.h>
#include <cstdio>
#include<iostream>
using namespace std;
int function(int n);
int main()
{
int n;
cin >> n;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(n<=0){
return(0);
}
else{
function(n);
}
}
int function(int n)
{
if (n<=9)
{
cout<<"experiment";
}
else{
cout<<"Greater than 9";
}
return 0;
}
The error with clang is:
<source>:20:9: error: reference to 'function' is ambiguous
function(n);
^
<source>:8:5: note: candidate found by name lookup is 'function'
int function(int n);
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/std_function.h:111:11: note: candidate found by name lookup is 'std::function'
class function;
^
// ... and more ....
For starters this else code block
else{
function(n);
}
returns nothing.
Though it is allowed but confuses readers of the program because they expect that if there is an explicit return statement in the if sub-statement then a similar return statement should be in the else sub-statement.
It seems the name function declared in the global name space conflicts with the standard name std::function due to the using directive.
using namespace std;
Write
else{
return ::function(n);
}
The problem is caused by #include <bits/stdc++.h> combined with the directive using namespace std.
<bits/stdc++.h> includes most (all, depending on the age of the version you have with your compiler) headers related to the C++ standard library.
One of the headers included by <bits/stdc++.h> (since C++11) is <functional>, which declares a templated class std::function. std::function has a templated constructor that can accept a single argument of any type.
In your main(), anything declared (visible to the compiler) named function is a candidate for being used by the statement function(n). The directive using namespace std tells the compiler to consider names within std as candidates. According to rules of the language, both your declared function() and std::function are equally good matches for the name function.
The real fix has two parts. The first is to avoid using headers like <bits/stdc++.h> and, instead, only include standard headers that are actually needed by your program.
The second part is to avoid using the directive using namespace std excessively, or even at all. It can cause names (of types, functions, variables, etc) within standard headers to accidentally match names in your code.
If you do a search, you will find plenty of explanations of why to avoid both <bits/stdc++.h> and to avoid using namespace std (or other using directives). Both have their uses, but both introduce hard-to-avoid gotchas (such as you have experienced).
Vlad has shown that working around the problems caused by using namespace std; can solve your problem. That is a good answer.
Funnily, you can also fix your problem by not applying the antipattern #include <bits/stdc++.h>. Even without Vlads proposed improvement.
#include <limits>
#include <cstdio>
#include<iostream>
using namespace std;
int function(int n);
int main()
{
int n;
cin >> n;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(n<=0){
return(0);
}
else{
function(n);
}
}
int function(int n)
{
if (n<=9)
{
cout<<"experiment";
}
else{
cout<<"Greater than 9";
}
return 0;
}
More info on why I dare to describe that as "antipattern" is here:
Why should I not #include <bits/stdc++.h>?
I am trying to create a lazy function from a template function following the Boost::phoenix documentation. The code looks like this
#include <iostream>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/function.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/phoenix/statement.hpp>
#include <boost/phoenix/object.hpp>
#include <boost/phoenix/function/adapt_function.hpp>
#include <boost/phoenix/core/argument.hpp>
using namespace boost;
using namespace boost::phoenix;
namespace demo
{
bool func(double a,double b)
{
return bool(a > b);
}
}
BOOST_PHOENIX_ADAPT_FUNCTION( bool , func , demo::func , 2)
int main(int argc,char **argv)
{
namespace pl = boost::phoenix::placeholders;
auto comperator = func(pl::arg1,pl::arg2);
std::cout<<comperator(1.2,12.4)<<std::endl;
std::cout<<comperator(0.5,0.1)<<std::endl;
}
This is virtually one of the examples from the BOOST documentation. Storing this file as mk_lazy1.cpp and try to compile gives
$ g++ -omk_lazy1 mk_lazy1.cpp
mk_lazy1.cpp:26:1: error: template argument 1 is invalid
mk_lazy1.cpp:26:1: error: expected identifier before ‘::’ token
mk_lazy1.cpp:26:1: error: expected initializer before ‘const’
mk_lazy1.cpp: In function ‘int main(int, char**)’:
mk_lazy1.cpp:31:10: error: ‘comperator’ does not name a type
mk_lazy1.cpp:32:35: error: ‘comperator’ was not declared in this scope
I use gcc-4.7 on a Debian testing system. An honestly I am a bit lost as I have absolutely no idea what is wrong here (as I said, this is virtually a word by word copy of one of the examples provided by the Boost documentation).
Does anyone have a good idea?
Remove using namespaces and all will work fine.
Or write using namespaces AFTER adapt macro and all will work fine too.
Or put macro into unnamed namespace.
So I was doing some simple C++ exercises and I noticed an interesting feat. Boiled down to bare metal one could try out compiling the following code:
class nice
{
public:
nice() {}
};
int main()
{
nice n;
return 0;
};
The result is a compilation error that goes something like this:
<file>.cpp: In function ‘int main()’:
<file>.cpp:11: error: expected `;' before ‘n’
<file>.cpp:11: warning: statement is a reference, not call, to function ‘nice’
<file>.cpp:11: warning: statement has no effect
And this was using regular g++ on Max OS X, some of my friends have tried in on Ubuntu as well, yielding the same result.
The feat seems to lie in the word "nice", because refactoring it allows us to compile. Now, I can't find the "nice" in the keyword listings for C++ or C, so I was wondering if anyone here had an idea?
Also, putting
class nice n;
instead of
nice n;
fixes the problem.
P.S. I'm a relative C++ newbie, and come from the ActionScript/.NET/Java/Python world.
Update:
Right, my bad, I also had an
#include <iostream>
at the top, which seems to be the root of the problem, because without it everything works just fine.
Maybe the problem is somehow caused by function nice in libc. It is similar to trying to name your class printf.
using namespace std, by any chance?
Edit:
The standard says that standard headers define all their symbols in namespace std (see 17.4.1.2.4).
A footnote, however, also says that the <.h> variants dump their names into the global namespace - but of course no one should be using these ;)
It is a namespace problem but not with namespace std. The header <iostream> is pulling in <unistd.h>
If you try
class nice
{
public:
nice() {};
};
int main(int argc, char *argv[])
{
nice n;
return 0;
}
there is no problem.
Simply add
#include <unistd.h>
and you will get the "expected ‘;’ before ‘n’" error. Namespace std does not enter the picture.
So the solution is the same as before - put class nice in its own namespace and it will not clash with the global ::nice().
Try this version:
#include <iostream>
namespace test
{
class nice
{
public:
nice() {}
};
};
using namespace std;
int main()
{
test::nice n;
cout << "well I think this works." << endl;
return 0;
}
In this case I've defined my own namespace test. Doing so, I can use whatever class names I like, including functions already defined like printf. The only things I can't re-use are reserved words like int or namespace.
Note: if you say:
using namespace test;
As well and refer to nice alone, you'll get this error:
nice.cpp: In function ‘int main()’:
nice.cpp:18: error: reference to ‘nice’ is ambiguous
/usr/include/unistd.h:593: error: candidates are: int nice(int)
nice.cpp:7: error: class test::nice
Which I think explains nicely what's going on - nice now exists in two namespaces and the compiler can't work out which one you mean.
It works fine for me. Did you try the exact code you posted?
extern "C"
{
#include <unistd.h>
}