I'd expect in the example bellow compiler will fail to compile the code, since it
doesn't know what is "find()", which defined in std namespace in algorithm header.
However this code compiles on RHEL 5.3 with gcc 4.1.2.
What do I miss?
#include <string>
#include <algorithm>
int main()
{
std::string s;
find(s.begin(), s.end(), 'a'); // should not compile
}
This works due to Argument Dependent Lookup. The function-template is searched in the namespace of the arguments types. In this case, the arguments are std::string::iterator, so the function is searched in the namespace std.
Related
I have a C++ code that uses endl, vector, complex, and cout occasionally without any namespace qualification. When compiling with GCC 4.9, I get errors like this one:
bfm.h:454:4: error: 'complex' does not name a type
complex<double> inner(Fermion_t x,Fermion_t y);
^
In the very same file, there are lines with an std:: qualifier:
std::complex<Float> dot(Fermion_t x_t, Fermion_t y_t,int sx,int sy);
Throughout the codebase, I saw the following template specializations used
std::complex<double>
std::complex<cFloat>
complex<Float>
complex<double>
complex<T>
complex<S>.
Neither for the regular express struct\s+complex nor class\s+complex I managed to find something in the codebase or the codebase of the base library. Therefore I assume that it indeed is the standard library complex type.
There are a couple of using namespace std scattered around in various header files, but not all of them.
I tried compiling this codebase with GCC 4.9 and Clang 3.7. Both give similar errors about the missing type. Is there some possibility that this has worked with an older version of GCC? I have tried to insert std:: at all the needed points but I have the impression that I do something wrong if I cannot just compile the source checkout that is meant for this type of computer.
you can use selective using... declarations or type aliasing to bring in only the std:: members you need. Like:
using std::complex;
using std::cout;
using std::endl;
cout << "Hello world" << endl; // works
complex<float> x; // works
fstream y; // compile error, no namespace qualification, no using declaration
std::fstream z; // OK
Ah, yes, maybe not that evident, so perhaps worth mentioning. You now that std::endl? Well, it's a stream manipulator, a function in fact.
Which means one can bring in the current block function members from other namespaces as well.
Like:
#include <cmath>
#include <cstdlib>
inline void dummy(float x) {
float y=fabs(x); // Na'a.., fabs is imported into std namespace by <cmath>
using std::itoa; // same is itoa, but we'll be using it
char buff[128];
itoa(42, buff, 10); // OK
}
I use VS 2015 (Update 3) to compile the following code:
#include <codecvt>
#include <cctype>
#include <functional>
int main()
{
std::function<int(int)> fn = std::isspace;
}
If I use VC++ to compile it, it's ok. However, if I change the compiler to Visual Studio 2015 - Clang with Microsoft CodeGen (v140_clang_c2) in Visual Studio, clang reports an error:
main.cpp(7,26): error : no viable conversion from '' to 'std::function'
std::function fn = std::isspace;
More surprising, if I comments the first line as follows, clang will also be ok.
//#include <codecvt> // now clang feels happy
#include <cctype>
#include <functional>
int main()
{
std::function<int(int)> fn = std::isspace;
}
What's the root cause?
std::isspace is overloaded in the standard library.
Due to the structure of their standard library headers, one compiler sees two different declarations of the name.
Then its use without arguments or casting is ambiguous.
std::isspace is ambiguous, it can either refer to the function found in <cctype> which is for compatibility with C, or the function template found in <locale>.
You can resolve the ambiguity with
std::function<int(int)> fn = static_cast<int(*)(int)>(std::isspace);
Or by omitting the std:: namespace, although technically there's no requirement for implementations to import the C functions into the global namespace.
The Clang and GCC implementations of <codecvt> both seem to include declarations of the template from <locale>, hence the error; presumably VS doesn't.
I'm playing around with my coding style. I used to explicitly prefix every library call with std:: but I'm switching over to using declarations like this:
using std::count;
using std::vector;
One thing I've noticed over the past few days is that sometimes if I forget a using declaration -- using std::vector; is a good example -- I get reams of compiler errors. However, if I neglect to namespace delcare an algorithm such as using std::count; my code compiles just fine.
Does this have to do with the difference with classes and free functions? On all the reference sites, both count(first, last, value) and vector are prefixed with std:: so I would expect them to behave the same.
Or does it have to do with other functions in the global namespace? I notice std::max also seems to require a namespace declaration, perhaps it defined in a default-included Apple/glibc/LLVM file and thus there is a conflict if I used it sans namespace declaration?
I am using Apple LLVM 7.0.2. on El Capitan.
EDIT: Show us the code
#include <algorithm>
#include <vector>
using std::count;
using std::vector;
int main() {
vector<int> v = { 1, 2, 3, 4 };
return count(begin(v), end(v), 3);
}
As T.C. (almost) said, the magic incantation is ADL, which stands for "argument-dependent lookup". When a function is called with an argument whose type is defined in a namespace, the compiler looks for the function in that same namespace. Makes, sense, right?
#include <stack>
#include <list>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
using namespace std;
void biggies(vector<string>& str,vector<string>::size_type sz)
{
sort(str.begin(),str.end());
auto end_unique=unique(str.begin(), str.end());
str.erase(end_unique,str.end());
//When I remove the "const" in the parameter list, the code can't compile
stable_sort(str.begin(), str.end(), [](const string&a,const string&b){return a.size()<b.size();});
auto wc=find_if(str.begin(), str.end(), [sz](string& a){return a.size()>=sz;});
for_each(wc, str.end(), [](string& s){cout<<s<<endl;});
}
int main()
{
vector<string>vec{"11","22","1","1111","2222","2","111","222"};
biggies(vec, 2);
}
I test the code in Xcode 6.4 and Visual Studio 2015 and it turns out that both cannot compile without the "const" in the parameter list. I wonder why the lack of "const" would disrupt the compilation? I'll be very thankful with your answers.
I can't find anything in the standard (N3337) that puts any specific requirements on the parameter types for a comparator passed to sorting-related algorithms. All I can find that kind of hints at why you're having this issue is this:
25.4.2: It is assumed that comp will not apply any non-constant function through the dereferenced
iterator.
It is somewhat indirect, but since it is 'assumed' that your comparator won't apply any non-const function to what's given to you by the algorithm, I guess it's valid that the algorithm pass const objects to it; this is likely the source of your problem.
I'm trying to understand why the code below compiles without problems in VS2012 and GCC 4.8.3:
#include <iostream>
#include <regex>
int main(int argc, char** argv)
{
std::wregex brackets_regex(L"");
std::wcmatch bracket_match;
wchar_t expr[80] = L"";
regex_search(expr, bracket_match, brackets_regex);
}
As far as I could find, regex_search is part of namespace std, but neither of the compilers require std::. Why is that allowed?
That code compiles because of Argument Dependent Lookup. Since the arguments are of types from the std namespace, that namespace is tagged as an 'associated namespace' and name resolution considers candidates from that namespace.
could that cause problems between boost and std namespaces?
It's possible it can create ambiguity, resulting in errors.
namespace A {
struct AA {};
}
namespace B {
struct BB {};
void foo(A::AA, BB) {}
}
namespace A {
void foo(AA, B::BB) {}
}
int main()
{
A::AA a;
B::BB b;
foo(a, b);
}
Also I think some compilers might implement it incorrectly, especially in conjunction with two-phase lookup, resulting in either compiling ill-formed code or failing to compile correct code, or even resolving a name to the wrong entity.
If you're encountering a problem you think might be related to ADL you'll have to provide details to get a more specific answer.