explicit specialization for overloading operator '<<' (left shift) - c++

Lets say i have a class, for which i want to overload an operator based on an enum type:
#include <iostream>
enum class option : char { normal, do_something_stupid };
class foo
{
public:
int i;
explicit foo(int a=0) : i(a) {};
/* overload operator '+=' based on 'option' */
template<option E = option::normal>
void operator+=(const foo& f) { i += f.i; }
};
/* explicit specialization for operator += */
template<> void foo::operator+=<option::do_something_stupid>(const foo& f)
{ i += (f.i +1000); }
int main()
{
foo f1(1), f2(2);
f1 += f2;
std::cout << "\nf1 = " << f1.i;
f1.operator+=<option::do_something_stupid>(f2);
std::cout << "\nf1 = " << f1.i;
std::cout << "\n";
return 0;
}
This builds clean (ignoring the fact that it really does something pretty dump) both on g++ and clang++.
What if i want to overload the '<<' operator the same way? A similar approach does not seem to work:
#include <ostream>
#include <iostream>
enum class option : char { normal, do_something_stupid };
class foo
{
public:
int i;
explicit foo(int a=0) : i(a) {};
template<option E = option::normal>
friend std::ostream& operator<<(std::ostream& o, const foo& f)
{ o << f.i; return o; }
};
template<> std::ostream&
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
{
o << f.i + 1000;
return o;
}
int main()
{
foo f1(1), f2(2);
std::cout << "\nf1= " << f1;
std::cout << "\nf2= ";
/* this triggers an error with g++ */
std::cout.operator<< <option::do_something_stupid>(f1);
std::cout << "\n";
return 0;
}
According to g++, the call from main to the operator is invalid:
error: no match for ‘operator<’ (operand types are ‘<unresolved overloaded function type>’ and ‘option’)
std::cout.operator<< <option::do_something_stupid>(f1);
clang++ on the other hand, produces a different error message:
lsfov.cc:20:1: error: 'operator<<' cannot be the name of a variable or data member
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
^
lsfov.cc:20:11: error: expected ';' at end of declaration
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
^
;
lsfov.cc:20:12: error: expected unqualified-id
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
^
lsfov.cc:33:15: error: reference to non-static member function must be called
std::cout.operator<< <option::do_something_stupid>(f1);
~~~~~~~~~~^~~~~~~~~~
which goes on listing possible overload of '<<' from the standard library (if i understand correctly), like:
/usr/bin/../lib/gcc/x86_64-redhat-linux/5.3.1/../../../../include/c++/5.3.1/ostream:108:7: note: possible target for call
operator<<(__ostream_type& (*__pf)(__ostream_type&))
^
/usr/bin/../lib/gcc/x86_64-redhat-linux/5.3.1/../../../../include/c++/5.3.1/ostream:117:7: note: possible target for call
operator<<(__ios_type& (*__pf)(__ios_type&))
^
What is going on? Is this kind of operator specialization possible/allowed? If so, what is the proper way to call the operator? Or is clang correct and the definition is ill formed?

I think clang doesn't like the declaration of the friend in relation to the specialisation. Re-ordering them does the trick.
enum class option : char { normal, do_something_stupid };
// forward declare the class and operator
class foo;
template<option E = option::normal>
std::ostream& operator<<(std::ostream& o, const foo& f);
// the class with the declared friend operator
class foo
{
private:
int i;
public:
explicit foo(int a=0) : i(a) {};
template<option E>
friend std::ostream& operator<<(std::ostream& o, const foo& f);
};
// the operator implementations
template<option E>
std::ostream& operator<<(std::ostream& o, const foo& f)
{ o << f.i; return o; }
template<> std::ostream&
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
{
o << f.i + 1000;
return o;
}
In addition, the operator<< used in the main is not a member cout, but rather a global.
int main()
{
foo f1(1), f2(2);
std::cout << "\nf1= " << f1;
std::cout << "\nf2= ";
/* this triggers an error with g++ */
operator<< <option::do_something_stupid>(std::cout, f1);
std::cout << "\n";
return 0;
}
Sample here. g++ is also happy with the code as above.
A note on operators in a non-deduced context. I assume you are using the code here in a greater project of some sort, but if the operator is being used with non-deduced parameters, it is often easier and clearer to implement the functionality in a member method or a free function (using friend as required).

Related

<< Operator Overload Failing using a Class and Namespace [duplicate]

myclass is a C++ class written by me and when I write:
myclass x;
cout << x;
How do I output 10 or 20.2, like an integer or a float value?
Typically by overloading operator<< for your class:
struct myclass {
int i;
};
std::ostream &operator<<(std::ostream &os, myclass const &m) {
return os << m.i;
}
int main() {
myclass x(10);
std::cout << x;
return 0;
}
You need to overload the << operator,
std::ostream& operator<<(std::ostream& os, const myclass& obj)
{
os << obj.somevalue;
return os;
}
Then when you do cout << x (where x is of type myclass in your case), it would output whatever you've told it to in the method. In the case of the example above it would be the x.somevalue member.
If the type of the member can't be added directly to an ostream, then you would need to overload the << operator for that type also, using the same method as above.
it's very easy, just implement :
std::ostream & operator<<(std::ostream & os, const myclass & foo)
{
os << foo.var;
return os;
}
You need to return a reference to os in order to chain the outpout (cout << foo << 42 << endl)
Even though other answer provide correct code, it is also recommended to use a hidden friend function to implement the operator<<. Hidden friend functions has a more limited scope, therefore results in a faster compilation. Since there is less overloads cluttering the namespace scope, the compiler has less lookup to do.
struct myclass {
int i;
friend auto operator<<(std::ostream& os, myclass const& m) -> std::ostream& {
return os << m.i;
}
};
int main() {
auto const x = myclass{10};
std::cout << x;
return 0;
}
Alternative:
struct myclass {
int i;
inline operator int() const
{
return i;
}
};

Move ADL Friend Declaration

Consider the following class:
template<class a>
class c
{
public:
int x = 0;
// not really templated
friend constexpr auto operator +( int const left,
c const & a ) noexcept
{
return c{ left + x };
}
};
How does one move the function body without declaring it in the outer scope? e.g. pseudo:
template<class a>
friend constexpr auto c<a>::operator +( int const left,
c const & a ) noexcept
{
return c{ left + x };
}
The first snippet of OP:
class c
{
public:
int x = 0;
friend constexpr auto operator +( int const left,
c const & a ) noexcept
{
return c{ left + x };
}
};
It shows a free function (operator) that is inline defined in class c as friend.
This is not a member function of class c although it may look so on the first glance.
(If it would be a member function it would be a ternary operator+ but there doesn't exist one in C++ nor can it be overloaded.)
The second snippet of OP:
friend constexpr auto c::operator +( int const left,
c const & a ) noexcept
{
return c{ left + x };
}
It is wrong for two reasons:
friend doesn't make sense. (friend to what?)
If it's a free function - scope c:: doesn't make sense.
The friendship of functions cannot be declared outside of the resp. class.
If this would be allowed everybody could declare friendship of functions everywhere which accesses the private members of classes. This would make the sense of private members somehow useless.
(Imagine a safe with an electronic lock and a key pad where the password is written on the door.)
(Original image by Binarysequence - Own work, CC BY-SA 4.0, Link)
Nevertheless, friend functions (and operators) can be defined non-inline, of course.
The following sample shows how:
#include <iostream>
// forward declaration of class c
class c;
// forward declaration of operator +
constexpr auto operator+(int, c const&) noexcept;
// the class c
class c {
// make operator + a friend to grant access to private members
friend constexpr auto operator+(int, c const&) noexcept;
private:
int x;
public:
c() = default;
constexpr c(int x): x(x) { }
int get() const { return x; }
};
// the operator +
constexpr auto operator+(int lhs, c const &rhs) noexcept
{
return c(lhs + rhs.x);
}
// show it in action:
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(c a(123));
DEBUG(std::cout << (234 + a).get() << '\n');
}
Output:
c a(123);
std::cout << (234 + a).get() << '\n';
357
Live Demo on coliru
This is similar when applied to templates (although the syntax is a bit more tricky):
#include <iostream>
// forward declaration of class c
template <typename T>
class c;
// forward declaration of operator +
template <typename T>
constexpr auto operator+(int, c<T> const&) noexcept;
// the class c
template <typename T>
class c {
friend constexpr auto operator+<>(int, c<T> const&) noexcept;
private:
T x;
public:
c() = default;
constexpr c(T x): x(x) { }
int get() const { return x; }
};
// the operator +
template <typename T>
constexpr auto operator+(int lhs, c<T> const &rhs) noexcept
{
return c(lhs + rhs.x);
}
// show it in action:
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(c<int> a(123));
DEBUG(std::cout << (234 + a).get() << '\n');
}
Output:
c<int> a(123);
std::cout << (234 + a).get() << '\n';
357
Live Demo on coliru
More about inline friend functions:
SO: friend AND inline method, what's the point ?
SO: c++ implementing friend/inline functions (similar question)
SO: Nonmember friend function is always inline (similar question)
The closest you can get is to define the function in a source file such that its out-of-class declaration is not visible to (other) clients. (You would not be able to have its return type be deduced in that case.) In C++20, you can do something very similar by not exporting the friend from a module.
It has been suggested that what you want should be achievable with a differently qualified definition:
constexpr auto ::operator +( int const left,
c const & a ) noexcept
{
return c{ left + x };
}
The otherwise redundant scope resolution operator would cause the definition to “not count” for name lookup, but GCC and Clang currently give it other interpretations: Clang does let ordinary lookup find the function (and issues a warning in the global scope case), while GCC rejects it entirely.

Overloading operator<< for a member structure defined in a template structure

Hello dear StackOverflowers!
I am having trouble with a template structure which comprises another (but non-template) structure.
Here's the thing:
Structure B is non-template and is defined inside a template structure A.
Strcure B is "protected" because it exists only for the purposes of structure A and no-one and nothing else shall use it outside of structure A.
There's an overload of operator<< for structure B, so that objects of type B can be sent to the standard output "cout << B_type_object;" (and it's A's friend so that it can access B which is protected).
The aforementioned printing of B objects is done only by methods defined in A (because of "2.").
As long as both structures are non-template everything works like a charm.
The moment A is a template I get an error message (provided in the code section).
Here is the working code (where A is not template):
#include <iostream>
#include <string>
struct A
{
protected:
struct B
{
std::string something;
B& operator= (const std::string&& rhs)
{
this->something = std::move(rhs);
return *this;
}
};
B B_object;
friend std::ostream& operator<< (std::ostream& output, const typename A::B& ob);
public:
void method ()
{
B_object = "This is text.";
//No error here
std::cout << B_object;
}
};
std::ostream& operator<< (std::ostream& output, const typename A::B& ob)
{
output << ob.something;
return output;
}
int main(int argc, const char * argv[])
{
A obj;
obj.method();
return 0;
}
This is the code which doesn't work
#include <iostream>
#include <string>
template <typename T>
struct A
{
T variable;
protected:
struct B
{
std::string something;
B& operator= (const std::string&& rhs)
{
this->something = std::move(rhs);
return *this;
}
};
B B_object;
template <typename X> friend std::ostream& operator<< (std::ostream& output, typename A/*<X>*/::B& ob);
public:
void method ()
{
B_object = "This is text.";
//ERROR: Invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'A<int>::B')
std::cout << B_object;
}
};
template <typename X>
std::ostream& operator<< (std::ostream& output, typename A<X>::B& ob)
{
output << ob.something;
return output;
}
int main(int argc, const char * argv[])
{
A<int> obj;
obj.method();
return 0;
}
Just declare the operator inline in B, then it works:
...
struct B
{
std::string something;
B& operator= (const std::string&& rhs)
{
this->something = std::move(rhs);
return *this;
}
friend std::ostream& operator<< (std::ostream& output, const typename A<T>::B& ob)
{
output << ob.something;
return output;
}
};
...
This has also the advantage that your are not friending any operator<< of any A<X>. In your example, the operator taking A<string>::B would also be a friend of A<int>::B. For a more in-depth explanation, see this answer:
https://stackoverflow.com/a/4661372/36565

Behavior of C++ templates and operator overloading

I would like to understand the following code behavior
#define USE_FRIEND
class Foo
{
public:
template <typename T>
Foo& operator<< (T val)
{
std::cout << "Inside Foo" << std::endl;
return *this;
}
};
class A
{
public:
#ifdef USE_FRIEND
friend Foo& operator<<(Foo& f, A& a)
{
std::cout << "Inside A" << std::endl;
return f;
}
#endif
};
int main()
{
A a;
Foo f;
#ifdef USE_FRIEND
std::cout << " using Friend :: ";
#else
std::cout << " not using Friend :: ";
#endif
f << a;
system("pause");
return 0;
}
The output for the above code for 2 executions, one with Using friend and another without:
case 1:
using Friend :: Inside A
case 2:
not using Friend :: Inside Foo
I can understand case 2, but can anyone explain case 1
Overload resolution is complicated business, but here are the two rules that are relevant:
The overloads that are viable are:
template <typename T> Foo & Foo::operator<<(T)
Foo & operator<<(Foo &, A &)
When you call operator<<(f, a), then both overloads match, and they both match on the nose, deducing T = A in the template. There is no difference in exactness, since a reference counts as a "perfect match".
Thus the two overloads are tied, and the resolution would appear to be ambiguous. However, there is a tie breaker: No 1 is a template and No 2 is not. In this case, the non-template is a better match.

Why can't I overload ostream's << operator?

EDIT: Passed Expression exp and string expression by const reference
I'm trying to allow a class to be display via cout in the following manner:
#include <iostream>
class Expression {
private:
std::string expression;
public:
Expression(const std::string& expression):
expression(expression) { }
friend std::ostream& operator <<(ostream& os, const Expression& exp) {
return os << exp.expression; }
};
however, on compiling I get the errors:
main.cpp(9) : error C2061: syntax error : identifier 'ostream'
main.cpp(9) : error C2809: 'operator <<' has no formal parameters
this is especially confusing because VC++ is giving me ostream as an autocompletion suggestion when I enter std::. What's causing these errors, and how can they be resolved?
Surely you need std::ostream in all locations? i.e.:
friend std::ostream& operator <<(std::ostream& os, Expression& exp) ...
^^^
Without a using namespace std; clause (which has its own set of problems), you need to fully qualify all the iostream stuff.
You can see this with the following program:
#include <iostream>
class Expression {
private:
std::string expression;
public:
Expression(std::string expression):
expression(expression) { }
// added this bit.
// _/_
// / \
friend std::ostream& operator <<(std::ostream& os, Expression& exp) {
return os << exp.expression; }
};
int main (void) {
Expression e ("Hi, I'm Pax.");
std::cout << e << std::endl;
return 0;
}
which prints out:
Hi, I'm Pax.
as expected.
And, as some comments have pointed out, you should pass the string as const-reference:
#include <iostream>
class Expression {
private:
std::string expression;
public:
Expression(const std::string& expression)
: expression(expression) {
}
friend std::ostream& operator <<(std::ostream& os, const Expression& exp) {
return os << exp.expression;
}
};
int main (void) {
Expression e ("Hi, I'm Pax.");
std::cout << e << std::endl;
return 0;
}