Surprisingly the below code compiles and runs without error on a variety of compilers and versions.
#include <iostream>
int main() {
endl(std::cout);
return 0;
}
Ideone link
How does it compile? I am sure there is no endl in global scope because a code like
std::cout << endl;
would fail unless using is used or else you need std::endl.
This behavior is called argument dependent lookup or Koenig lookup. This algorithm tells the compiler to not just look at local scope, but also the namespaces that contain the argument's type while looking for unqualified function call.
For ex:
namespace foo {
struct bar{
int a;
};
void baz(struct bar) {
...
}
};
int main() {
foo::bar b = {42};
baz(b); // Also look in foo namespace (foo::baz)
// because type of argument(b) is in namespace foo
}
About the piece of code referred in question text:
endl or std::endl is declared in std namespace as following:
template< class CharT, class Traits >
std::basic_ostream<charT,traits>& endl( std::basic_ostream<CharT, Traits>& os );
or
std::ostream& endl (std::ostream& os);
And cout or std::cout is declared as
extern std::ostream cout;
So calling std::endl(std::cout); is perfectly fine.
Now when one calls just endl(std::cout);, because the type of argument cout is from std namespace, unqualified supposedly a function endl is searched in std namespace and it is found succesfully and confirmed to be a function and thus a call to qualified function std::endl is made.
Further reading:
GOTW 30: Name Lookup
Why does 'std::endl' require the namespace qualification when used in the statement 'std::cout << std::endl;", given argument-dependent lookup?
It is the way the stream manipulators work.
Manipulators are functions that passed to operator << as arguments. Then within the operator they are simply called.
So you have function declared like
template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
and you pass its pointer to operator <<. And inside the operator that declared something like
ostream& ostream::operator << ( ostream& (*op)(ostream&));
the function is called.like
return (*endl )(*this);
Thus when you see record
std::cout << std::endl;
then std::endl is function pointer that is passed to the operator << as argument.
In the record
std::endl( std::cout );
namespace prefix before name endl may be omitted because in this case the compiler will use the Argument Dependent Lookup. Thus this record
endl( std::cout );
will compile successfully.
However if to enclose the function name in parentheses then ADL is not used and the following record
( endl )( std::cout );
will not compiled.
Related
I'm studying overloaded operators.
I don't get the difference between using the <<-operator on a double / an std::string.
int main()
{
double a = 12;
string s = "example";
operator<<(cout, a); //doesn't work
cout.operator<<(a); //works
operator<<(cout, s); //works
cout.operator<<(s); //doesn't work
}
Why aren't operator<<(cout, a) and cout.operator<<(s); working?
Because that operator is defined as a member function, not as a free function.
Operators can be overloaded in those two ways, which when used with regular operator syntax will be transparent to the user. However, when using explicit syntax, you have to use the one specific to the actual function definition.
This example shows the difference in practice:
class Stream {
Stream& operator<<(Inside);
};
Stream& operator<<(Stream&, Outside);
For std::string, Outside way is used. For double, Inside is.
You can define operators in two different ways, as a member of a class and as free-standing function taking two arguments.
The operator accepting a double value is implemented as a member function of std::ostream, see cpp reference. You'll notice that there is no overload for char const* or std::string provided. These are defined separately, as free-standing functions, among some others.
Those operators defined as members (only!) work with the cout.operator<<(argument) notation, the free-standing ones with the two-argument variant.
However, all these differences are hidden away if you use the operators as they are intended:
std::cout << whatEver;
Because a non-class operator << for the types std::basic_ostream & and double (or const double &) is not defined in C++.
Such an operator that takes one argument of the type double is declared in the class std::basic_ostream as a member function.
basic_ostream<charT, traits>& operator<<(double f);
For objects of the type std::string the operator is declared as a stand-alone (non a class member) function the following way
template<class charT, class traits, class Allocator>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os,
const basic_string<charT, traits, Allocator>& str);
std::basic_ostream provides some << implementations (for basic types) as member functions. For other types (such as for std::basic_string), operator << is implemented as a free function. That's how the standard specifies it.
This is only a problem if you're invoking the operator using explicit function call notation (like in your code). The natural way to use it is using operator notation (cout << x), where the problem does not happen, as both member and free functions can be invoked by it.
You are using operator not in the right way.
operators may be implemented as member functions or non-member.
when running
cout.operator <<(a);
cout << a;
cout.operator <<(s);
cout << s;
you are calling the class operarator implementation;
but when you call
operator<<(cout, a);
where is the implementation ? o_O
Working example tested vc++13 & gcc(here)
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main(int argc, char* argv[])
{
int number = 13;
float pi = 3.13f;
double dp = 2.23233;
cout << "number: " << number << endl;
cout << "pi: " << pi << endl;
cout << "double: " << dp << endl << endl;
cout.operator <<(number) << endl;
cout.operator <<(pi) << endl;
cout.operator <<(dp);
}
Comment if need member or non-member implementation of example type.
I'm trying to use an std::initializer_list as an argument in a function that uses argument-dependent lookup (ADL). But I don't get it to work and I don't understand why. The following is a minimal failing example:
#include <initializer_list>
#include <iostream>
class Foo {
public:
inline friend void bar(std::initializer_list<Foo> v) {
std::cout << "size = " << v.size() << std::endl;
}
};
void baz(std::initializer_list<Foo> v) {
std::cout << "size = " << v.size() << std::endl;
}
int main(){
Foo a;
//bar({a,a}); // error: use of undeclared identifier 'bar'
baz({a,a}); // works
return 0;
}
As seen above, an equivalent global function works just fine. Why does the above not work?
I'm using clang on OS X 10.10.
I believe that the problem is that the subexpression1 { a, a } does not really have a type, and as such it does not have associated types or namespaces which in turn means that ADL does not kick in. If you have a function in the global namespace, normal lookup will find it, and it will find that { a, a } can match the function call as the initializer for std::initializer_list<Foo>.
1 The syntax { a, a } is called braced-init-list and it is not really an expression (or subexpression) in the language.
When the compiler sees bar({a,a}), it doesn't know the type of the arguments, so it searches for bar in the global namespace (::), and nowhere else. If you changed that line to Foo{a,a}, then it knows the argument is a Foo, and so also searches the Foo class for functions.
Following the question How can I detect if a type can be streamed to an std::ostream? I've written a trait class that says if some type can be streamed to an IO stream. The trait has seemed to work well until now that I've discovered a problem.
I'm using the code inside a project that uses LLVM and I'm using their StringRef class (which is similar in spirit to the proposed std::string_view). Here is a link to the Doxygen doc for the class, from where you can find it's declaration header file if needed. Since LLVM doesn't provide an operator<< to stream StringRef objects to std streams (they use a custom lightweight stream class), I've written one.
However, when I use the trait it doesn't work if my custom operator<< is declared after the trait (this happens because I have the trait in one header and the operator<< function in another one). I used to think that the lookup in template instantiations worked from the point of view of the instantiation point, so I thought it should work. Actually, as you can see below, with another class and its custom operator<<, declared after the trait, everything works as expected (that's why I've discovered this problem only now), so I can't figure out what makes StringRef special.
This is the complete example:
#include <iostream>
#include "llvm/ADT/StringRef.h"
// Trait class exactly from the cited question's accepted answer
template<typename T>
class is_streamable
{
template<typename SS, typename TT>
static auto test(int)
-> decltype(std::declval<SS&>() << std::declval<TT>(),
std::true_type());
template<typename, typename>
static auto test(...) -> std::false_type;
public:
static const bool value = decltype(test<std::ostream,T>(0))::value;
};
// Custom stream operator for StringRef, declared after the trait
inline std::ostream &operator<<(std::ostream &s, llvm::StringRef const&str) {
return s << str.str();
}
// Another example class
class Foo { };
// Same stream operator declared after the trait
inline std::ostream &operator<<(std::ostream &s, Foo const&) {
return s << "LoL\n";
}
int main()
{
std::cout << std::boolalpha << is_streamable<llvm::StringRef>::value << "\n";
std::cout << std::boolalpha << is_streamable<Foo>::value << "\n";
return 0;
}
Contrary to my expectations, this prints:
false
true
If I move the declaration of the operator<< for StringRef before the trait declaration, it prints true.
So why is this strange thing happening and how can I fix this issue?
As mentioned by Yakk this is simply ADL: Argument Dependent Lookup.
If you don't want to bother, just remember that you should always write a free function in the same namespace as at least one of its arguments. In your case, since it's forbidden to add functions to std, it means adding your function into the llvm namespace. The fact that you needed to qualify the StringRef argument with llvm:: was a dead give away.
The rules of function resolution are fairly complex, but as a quick sketch:
name lookup: collects a set of potential candidates
overload resolution: picks the best candidate among the potentials
specialization resolution: if the candidate is a function template, check for any specialization that could apply
The name lookup phase which we are concerned with here is relatively simple. In short:
it scans the argument's namespaces, then their parents, ... until it reaches the global scope
then proceeds by scanning the current scope, then its parent scope, ... until it reaches the global scope
Probably to allow shadowing (like for any other name lookup), the lookup stops at the first scope in which it encounters a match, and haughtily ignore any surrounding scope.
Note that using directives (using ::operator<<; for example) can be used to introduce a name from another scope. It is burdensome though, as it puts the onus on the client, so please don't rely on its availability as an excuse for sloppiness (which I've seen done :x).
Example of shadowing: this prints "Hello, World" without raising an ambiguity error.
#include <iostream>
namespace hello { namespace world { struct A{}; } }
namespace hello { void print(world::A) { std::cout << "Hello\n"; } }
namespace hello { namespace world { void print(A) { std::cout << "Hello, World\n"; } } }
int main() {
hello::world::A a;
print(a);
return 0;
}
Example of interrupted search: ::hello::world yielded a function named print so it was picked out even though it does not match at all and ::hello::print would have been a strictly better match.
#include <iostream>
namespace hello { namespace world { struct A {}; } }
namespace hello { void print(world::A) { } }
namespace hello { namespace world { void print() {} } };
int main() {
hello::world::A a;
print(a); // error: too many arguments to function ‘void hello::world::print()’
return 0;
}
When I types the following as a stand-alone line:
std::endl;
I got the following error:
statement cannot resolve address for overloaded function
Why is that? Cannot I write std::endl; as a stand-alone line?
Thanks.
std::endl is a function template. Normally, it's used as an argument to the insertion operator <<. In that case, the operator<< of the stream in question will be defined as e.g. ostream& operator<< ( ostream& (*f)( ostream& ) ). The type of the argument of f is defined, so the compiler will then know the exact overload of the function.
It's comparable to this:
void f( int ){}
void f( double ) {}
void g( int ) {}
template<typename T> void ft(T){}
int main(){
f; // ambiguous
g; // unambiguous
ft; // function template of unknown type...
}
But you can resolve the ambiguity by some type hints:
void takes_f_int( void (*f)(int) ){}
takes_f_int( f ); // will resolve to f(int) because of `takes_f_int` signature
(void (*)(int)) f; // selects the right f explicitly
(void (*)(int)) ft; // selects the right ft explicitly
That's what happens normally with std::endl when supplied as an argument to operator <<: there is a definition of the function
typedef (ostream& (*f)( ostream& ) ostream_function;
ostream& operator<<( ostream&, ostream_function )
And this will enable the compiler the choose the right overload of std::endl when supplied to e.g. std::cout << std::endl;.
Nice question!
The most likely reason I can think of is that it's declaration is:
ostream& endl ( ostream& os );
In other words, without being part of a << operation, there's no os that can be inferred. I'm pretty certain this is the case since the line:
std::endl (std::cout);
compiles just fine.
My question to you is: why would you want to do this?
I know for a fact that 7; is a perfectly valid statement in C but you don't see that kind of rubbish polluting my code :-)
std::endl is a function template. If you use it in a context where the template argument cannot be uniquely determined you have to disambiguate which specialization you mean. For example you can use an explicit cast or assign it to a variable of the correct type.
e.g.
#include <ostream>
int main()
{
// This statement has no effect:
static_cast<std::ostream&(*)(std::ostream&)>( std::endl );
std::ostream&(*fp)(std::ostream&) = std::endl;
}
Usually, you just use it in a context where the template argument is deduced automatically.
#include <iostream>
#include <ostream>
int main()
{
std::cout << std::endl;
std::endl( std::cout );
}
std::endl is a manipulator. It's actually a function that is called by the a version of the << operator on a stream.
std::cout << std::endl
// would call
std::endl(std::cout).
http://www.cplusplus.com/reference/iostream/manipulators/endl/
You can't have std::endl by itself because it requires a basic_ostream as a type of parameter. It's the way it is defined.
It's like trying to call my_func() when the function is defined as void my_func(int n)
endl is a function that takes a parameter. See std::endl on cplusplus.com
// This works.
std::endl(std::cout);
The std::endl terminates a line and flushes the buffer. So it should be connected the stream like cout or similar.
#include<iostream>
#include<conio.h>
#include<string.h>
using namespace std;
class student{
private:
string coursecode;
int number,total;
public:
void getcourse(void);
void getnumber(void);
void show(void);
};
void student ::getcourse(){
cout<<"pleas enter the course code\n";
cin>>coursecode;
}
void student::getnumber(){
cout<<"pleas enter the number \n";
cin>>number;
}
void student::show(){
cout<<"coursecode is\t\t"<<coursecode<<"\t\t and number is "<<number<<"\n";
}
int main()
{
student s;
s.getcourse();
s.getnumber();
s.show();
system("pause");
}
#include "stdafx.h"
#include "Record.h"
template<class T>//If I make instead of template regular fnc this compiles
//otherwise I'm getting an error (listed on the very bottom) saying
// that operator << is ambiguous, WHY?
ostream& operator<<(ostream& out, const T& obj)
{
out << "Price: "
<< (obj.getPrice()) << '\t'//this line causes this error
<< "Count: "
<< obj.getCount()
<< '\n';
return out;
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<Record> v;
v.reserve(10);
for (int i = 0; i < 10; ++i)
{
v.push_back(Record(rand()%(10 - 0)));
}
copy(v.begin(),v.end(),ostream_iterator<Record>(cout, "\n"));
return 0;
}
//Record class
class Record
{
private:
int myPrice_;
int myCount_;
static int TOTAL_;
public:
Record(){}
Record(int price):myPrice_(price),myCount_(++TOTAL_)
{/*Empty*/}
int getPrice()const
{
return myPrice_;
}
int getCount()const
{
return myCount_;
}
bool operator<(const Record& right)
{
return (myPrice_ < right.myPrice_) && (myCount_ < right.myCount_);
}
};
int Record::TOTAL_ = 0;
Error 2 error C2593: 'operator <<' is ambiguous
The concept behind operator<<( ostream &, ... ) is that every class can have its own overload, handling that specific class in a way that make sense.
That means you get operator<<( ostream &, const Record & ) which handles Record objects, and operator<<( ostream &, const std::string & ) which handles standard strings, and operator<<( ostream &, const FooClass & ) which handles FooClass objects. Each of these functions knows how to handle the object type it has been declared for, because each of them requires a different handling. (E.g. getPrice() / getCount() for Record, or getFoo() / getBar() for FooClass.)
Your template is trampling roughshod over the whole concept. By defining it as a template function (which would match any class), you not only collide with the many definitions of operator<<() already in the standard / your codebase, but all possible overloadings.
How could the compiler decide whether to use operator<<( ostream &, const std::string & ) or your template? It cannot, so it throws up its hands in despair and gives up. That's what the error is telling you.
First, you need to read the error message more carefully. As an alternative, consider breaking the statement up, something like this:
out << "Price: ";
out << (obj.getPrice());
out << "\tCount: ";
out << obj.getCount();
out << '\n';
When you do, you'll realize that what's really causing the problem is not where you try to print out getPrice(), but where you try to print out "Price: ".
The problem is arising because the compiler doesn't know whether to use the normal overload to print out the string, or to use the template being defined to print it out. The latter would cause infinite recursion, and it couldn't actually compile since it requires an object on which you can/could call getPrice and getCount to compile correctly -- but it has a signature that matches, so the compiler says it's ambiguous, and that's the end of that.
The reason of the error is that your templated overload is conflicting with another templated overload, and there is no reason to prefer one template to another:
template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
template <class T>
basic_ostream<char, char_traits<char> >& operator<< (basic_ostream<char, char_traits<char> >&, const T&);
//which one is preferable when you ask for: cout << "literal";?
(ostream should be a typedef for basic_ostream<char, char_traits<char> >.)
The whole idea of making your overload a template is questionable, seeing that the overload clearly cannot handle any other class than your Record.
There probably are techniques to allow you to provide a single templated overload for a number of unrelated Record-like classes with a little template metaprogramming (enable_if and traits), if that is the idea.