Consider the following simple classes, which I've contrived based on issues I'm seeing with a real project. Triple is a quick boiler-plate type for use with the inner constexprs in class Foo:
#include <iostream>
class Triple {
public:
friend
std::ostream & operator <<(std::ostream & o, Triple const & t);
constexpr Triple() : a_(0), b_(0), c_(0) { }
constexpr Triple(Triple const & other) = default;
constexpr Triple(double a, double b, double c)
: a_(a), b_(b), c_(c)
{ }
~Triple() = default;
private:
double a_, b_, c_;
};
std::ostream & operator <<(std::ostream & o, Triple const & t) {
o << "(" << t.a_ << ", " << t.b_ << ", " << t.c_ << ")";
return o;
}
class Foo {
public:
Foo() : triple_(defaultTriple) { }
Triple const & triple() const { return triple_; }
Triple & triple() { return triple_; }
constexpr static float defaultPOD{10};
constexpr static Triple defaultTriple{11.0, 22.0, 33.0};
private:
Triple triple_;
};
If I then write a main() function to use the public inner constexprs from Foo, as follows, it will fail to link (using g++ 4.7.0, by way of mingw-x86-64 on Windows 7):
int main(int argc, char ** argv) {
using std::cout;
using std::endl;
cout << Foo::defaultPOD << endl;
cout << Foo::defaultTriple << endl;
}
$ g++ -o test -O3 --std=c++11 test.cpp
e:\temp\ccwJqI4p.o:test.cpp:(.text.startup+0x28): undefined reference to `Foo::defaultTriple' collect2.exe: error: ld returned 1 exit status
However, if I write
cout << Triple{Foo::defaultTriple} << endl
instead of simply
cout << Foo::defaultTriple << endl
it will link and run fine. I can see that the former expresses more explicitly that a compile-time literal is what's intended, but I'm still surprised the latter won't work as well. Is this a compiler bug, or is there a reason based on the rules for constexpr that only the first example should work?
I would try other compilers to get more insight, but at present GCC 4.7.0 is the only one I have access to that supports constexpr.
Note also that the expression for the pod constexpr works fine without an explicit literal wrapper, e.g. cout << Foo::defaultPOD has never given me trouble.
A constant expression that appears in a context where a constant expression is not required may be evaluated during program translation but it is not required to be, so it might be evaluated at run time.
If a constexpr static member is evaluated during program translation the compiler can use its initializer to determine its value and won't need the member's definition.
If the member is used in a context that is evaluated at run time then its definition will be required.
In cout << Foo::defaultTriple << endl your compiler is generating the code to perform the lvalue-to-rvalue conversion of Foo::defaultTriple at run time so the object needs a definition.
In cout << Triple{Foo::defaultTriple} << endl the compiler is evaluating Foo::defaultTriple during program translation to create the temporary Triple that itself is probably evaluated at run time.
Unless your constexpr objects are only evaluated in contexts where constant expressions are required, you must provide a definition for them.
defaultPOD and defaultTriple declared inside the class is not a definition. You must define them outside of the class declaration if you want to use them in places that need to know their address.
So why does cout << Foo::defaultPOD << endl; work, but cout << Foo::defaultTriple << endl; doesn't?
defaultPOD is declared as a float, so when you do cout << Foo::defaultPOD it calls the operator<<(float val); which takes its argument by value. No definition is required in this call because you are only using the value (it's not odr-used as defined by 3.2.3). If you try to pass Foo::defaultPOD to a function that takes a reference, you would need to define it.
However, Foo::defaultTriple fails because operator << takes a Triple by reference requiring Foo::defaultTriple to be defined. However, even after changing the operator<< to pass by value, in my tests, I still ended up with a linker error. Only if I remove the member variables from Triple and make operator<< pass by value will the code compile without defining the static member variables. (When you remove the member variables from Triple the compiler optimizes out the variable I believe).
(Here is a nice reference which explains some of this stuff).
The error comes from the linker, it can not find the Foo::defaultTriple static member.
The issue here is the difference between "declaration" and "definition". The static line in your class is the declaration, you also need a definition. In C++, every static field defined inside a class should be also present inside a .cpp file:
// .hpp
class X {
static int Q;
};
// .cpp
int X:Q = 0;
In your case, you should have this line somewhere in a .cpp file:
Triple foo::defaultTriple;
Related
The main problem is that when typing cout<<f1; alone it worked as well as f1++; alone but when attempting to enter cout<<f1++; together it shows that error knowing that when making the post increment it is returning a fraction object.
ostream& operator <<(ostream& output, fraction& fraction1)
{
output << "[" << fraction1.num << "/" << fraction1.denom << "]" << endl;
return output;
}
fraction fraction::operator ++(int)
{
fraction temp = *this;
++(this->num);
++(this->denom);
return temp;
}
int main()
{
fraction f1;
cout << f1;
f1++;
cout << f1++ << endl; // Results in compiler error
return 0;
}
The compiler error is: no operator "<<" matches these operands
Reasoning by analogy, consider this setup:
void doSomething(int& x) {
x = 137;
}
int main() {
doSomething(42); // Oops!
}
This code won’t compile because there’s an error in the indicated line. The function doSomething expects an int&, which you can think of as meaning “please give me an actual int variable or int object somewhere that I can change.” But 42 isn’t an int variable - it’s a pure value, hence the error.
Now, suppose you change main to this:
int main() {
int var = 42;
doSomething(var++); // Oops!
The expression var++ means “increment var, then hand back the value it used to have.” That means that we’re still passing the pure value 42 into the function, and since the function wants objects and not values, this won’t compile.
However, you can make this version of main work by changing doSomething to take in a const int&:
void doSomething(const int& x) {
// do something other than change x
}
This code works just fine due to how C++ defines const references. Unlike a regular reference, which means “I’d like to be able to change this object,” a const reference works fine when you pass in a pure value, since the const bit means “I promise not to actually change anything here.”
Now, look at your code. It’s basically the same idea as what’s shown above: you have a function named operator<< whose second parameter is a fraction&. That means that you can’t pass in the result of the ++ operator. And the fix is the same - just change the second parameter to use a const reference.
Hope this helps!
Consider the following types:
#include <iostream>
typedef unsigned long long usize_t;
typedef unsigned __int16 uword_t;
typedef uword_t clockval_t; // time without seconds in format HHMM
std::string toString(clockval_t nClock)
{
return std::to_string((usize_t)nClock/100) + ":" + std::to_string((usize_t)nClock % 100);
}
std::string toString(uword_t nValue)
{
return std::to_string((usize_t)nValue);
}
void test(void)
{
uword_t val = 1;
clockval_t time = 1023; // 10:23
std::cout << "Value: " << toString(val);
std::cout << "time: " << toString(time);
}
Now when I try to compile this, I get an error from the compiler telling me that the std::string toString(clockval_t) already has a body. I understand why this happens of course, because the typedef is just an alias for uword_t.
AFAIK the only solutions are to provide a separate method:
std::string toClockString(clockval_t);
or make it an object:
class clockval ...
Is this correct or is there some other way to make the compiler choose the correct overload?
Even if there were a way to make compiler choose correct version, do you realize how it would be error-prone? Luckily, there is no such way because typedef creates alias and nothing more.
I suggest that you convert it into class. If you provide proper constructor and conversion operator then you even don't need to change parts of code which make use of clockval_t:
class clockval_t {
public:
clockval_t(uword_t aValue) : value(aValue) {}
operator uword_t() const { return value; }
private:
uword_t value;
};
...
clockval_t time = 1023; // works fine
std::cout << time << std::endl; // works fine
std::cout << (time / 10) << std::endl; // works fine
Is this correct or is there some other way to make the compiler choose the correct overload?
Yes you're correct, you can't overload on typedef since it's simply an alias. As you rightly suggest, either rename the function or create a new type with class. Adding a fake parameter simply to change the function signature is usually a bad idea, renaming is clearer.
The meaning of typedef is defined in the standard as (7.1.3 The typedef specifier):
Within the scope of its declaration, a typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier (...). A typedef-name is thus a synonym for another type. A typedef-name does
not introduce a new type (...).
Therefore the two functions are indeed ambiguous in regard to the type of input parameter. You need to distinguish the type (e.g. by using different type, e.g. a class or enum) or perhaps add a second parameter (maybe with a default value) indicating which kind type exactly is being passed in.
Link to original answer: https://softwareengineering.stackexchange.com/questions/254473/in-which-stage-of-compilation-is-typedef-resolved-by-the-compiler
When declaring and using static const integrals, I find it convenient and natural to use the object reference I'm working with to access the variable, rather than fully-qualifying it with the class name. I'm wondering if there is a downside to this? Take for example:
class MyLongClassNameIdRatherNotHaveEverywhere {
public:
static const int Len = 6;
//...
void otherInterestingThings();
void someWorkToDo();
};
int main() {
MyLongClassNameIdRatherNotHaveEverywhere *lcn = new MyLongClassNameIdRatherNotHaveEverywhere;
lcn->someWorkToDo();
cout << "the length is: " << lcn->Len << endl;
delete lcn;
return 0;
}
Notice the lcn->Len... it's really a constant, and in fact if lcn were null, lcn->Len would still compile and run just fine. I could have written MyLongClassNameIdRatherNotHaveEverywhere::Len there instead, which certainly makes it more obvious (to me at least) that this is a constant. Are there other drawbacks?
Apart from weirdness, I can see a drawback in case operator -> is overloaded...
Scope resolution operator :: btw, cannot be overloaded.
I've always been taught that
1. Class c(arg);
and
2. Class c = arg;
are two totally equivalent statements, but look at this situation.
#include <iostream>
class Intermediary {
};
class Left {
public:
Left(const Intermediary &) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
class Right {
public:
// The argument is there just so that the example can work, see below
Right(int) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
operator Intermediary () const {
std::cout << __PRETTY_FUNCTION__ << std::endl;
return Intermediary();
}
};
Now if I do this:
Left l = Right(0);
The compiler will complain
error: conversion from Right to non-scalar type Left requested
But if I do this:
Left l(Right(0));
Then everything compiles and the output is
Right::Right(int)
Right::operator Intermediary() const
Left::Left(const Intermediary&)
However, if I do this:
Left l = (Intermediary)Right(0);
then everything compiles again and the output is just like the one above.
So obviously
1. Class c(arg);
and
2. Class c = arg;
are not the same, but why not, and what's the difference? I couldn't find anything about this online.
I've always been taught that Class c(arg); and Class c = arg; are two totally equivalent statements, but look at this situation.
It turns out they are not equivalent. The first one constructs the Class c out of an arg, while the second one constructs a Class out of an arg and then copy-constructs Class c out of it. Note that the implementation is allowed to ellide that copy, and it usually does.
Left l = Right(0);
This requires a conversion from Right to Intermediary, and one from Intermediary to Left. This two sequential user defined conversions are not allowed by the standard, you have to do at least one of them explicit as you do with:
Left l = (Intermediary)Right(0);
i need someone who explain me these lines of code part by part and i need some help in using "ostream" with simple examples. thank you :).
inline std::ostream& operator<<(std::ostream& os, const Telegram& t)
{
os << "time: " << t.DispatchTime << " Sender: " << t.Sender
<< " Receiver: " << t.Receiver << " Msg: " << t.Msg;
return os;
}
UPDATE 1: when i use this function it doesnt compile and the error says:
std::ostream& class::operator<<(std::ostream& os, const Telegram& t) must take exactly one argument
These line are simply adding the ability to handle Telegram objects to the standard output stream class.
When you add a new class and you want output streams like cout to intelligently handle them, you need to add a new << operator method which has the new object type as the second argument.
What the code above is doing is exactly that. When you later execute the statements:
Telegram tg("Bob", "Hello, how are you?");
cout << tg;
that function in your question will be called with the stream as the first argument and your tg object as the second argument and it will then be able to output the data in a format suitable to the class.
This was actually one of the early C++ things I had trouble getting my head around. Although the class is supposed to be self-contained, you're actually adding something to a different class to handle the output. Once you understand why this is happening (because it's the ostream class that is responsible for outputting things rather than your own class), it will hopefully make sense.
Hopefully making it clearer with a simpler example:
1 inline std::ostream& operator<<(std::ostream& os, const Telegram& t) {
2 os << "message: " << t.Msg;
3 return os;
4 }
Line 1 is simply the function definition. It allows you to return the stream itself (that you pass in) so you can chain << segments. The operator<< is simply the function you're providing, which is the one called when you put << tg into an output stream statement.
Line 2 uses more basic << statements that have already been defined (in this case, whatever type Msg is, probably a string).
Then line 3 returns the stream, again to allow chaining of << segments.
The basic idea is to provide operator<< functions that build on existing operator<< function for the data types that constitute your type.
And with a simple wrapper class containing just an int:
#include <iostream>
// This is my simple class.
class intWrapper {
public:
intWrapper (int x) { myInt = x; };
int getInt (void) { return myInt; }
private:
int myInt;
// Must be friend to access private members.
friend std::ostream& operator<< (std::ostream&, const intWrapper&);
};
// The actual output function.
inline std::ostream& operator<< (std::ostream& os, const intWrapper& t) {
os << "int: " << t.myInt;
return os;
}
// Main program for testing.
// Output with getter and with ostream.
int main (void) {
class intWrapper x(7);
std::cout << x.getInt() << std::endl; // ostream already knows about int.
std::cout << x << std::endl; // And also intWrapper, due to the
// function declared above.
return 0;
}
This outputs:
7
int: 7
the first by just calling the getter function to retrieve the integer, the second by calling the << operator function we added to ostream.
The function you posted (henceforth "the function") is an overload of the insertion operator, operator <<. It allows you to output an object of type Telegram, or any other type deriving from Telegram or convertible to a Telegram, to an output stream. This is similar in spirit to the common use of IO streams in C++:
std::cout << 0 << '\n';
Here you output the int 0 followed by the char newline to the standard output stream. With the function you posted you can now do something like
Telegram tel; // if Telegram has a default constructor
std::cout << tel << '\n';
something you would otherwise not been able to do, because the standard C++ library doesn't know about your new Telegram type and so never defined how to output objects of this type.
In code:
inline std::ostream& operator<<(std::ostream& os, const Telegram& t)
The first line starts with the inline keyword. Presumably the function is defined in a header file, and so in that case you must use the inline keyword so the definition does not violate the one definition rule.
That is, every time you include the header in an implementation file you get the function defined for that implementation file. When the linker comes in to link together all the compiled object files it will find multiple definitions of the function, one in each implementation file that included the header with the function you posted. This is something C++ forbids; C++ demands a function may be implemented no more than one time, and exactly one time if you intend to call it.
The use of the inline keyword essentially asks the C++ compiler to make sure that function is not defined more than once in such a way that the linker jumps off its seat and complains about the ambiguity of multiple definitions to choose from.
Here I argue it's a bad idea to inline the function. It would be a better idea to remove the inline keyword and move the function definition to its own translation unit, or implementation file. This way the function will compile exactly once, as opposed to once for each implementation file that includes the header with the function.
Next you will notice that function is a free function, as opposed to a member function. This allows (requires, as a matter of fact) the function to specify the operator's left operand, the stream object. This means the function will work with any object that is convertible to a stream. It also means you don't need to modify a class to add this extension to output semantics. If the function would be a member then you'd have to change the header of the class, which in turns means recompiling all implementation files that include that header. Granted, it appears your function is defined in a header; that's probably a bad idea, as I explained above.
Next you see that the function returns a std::ostream. std::ostream is in fact typedef'd as std::basic_ostream<char, std::char_traits<char> >, and therefore your function can only output Telegram objects to streams that work on char types.
The reason the function returns a std::ostream is so that you can chain calls to the function. If you look carefully,
std::cout << 0 << 1;
is in fact a chain of two calls to the insertion operator overload function. Once to output 0, and then to output 1. It is equivalent to
std::operator<<(std::operator<<(std::cout, 0), 1);
The first call to insert 0 returns an output stream, and the second call to insert 1 takes that returned output stream and inserts into that 1. That's why we return the output stream: so we can chain calls.
You will also note that the insertion operator has a left-to-right associativity, which means that in the above statement 0 is guaranteed to be output first, and 1 second. This as opposed to the equivalent line I wrote above, in which the associativity (of function calls) is inside-out. This yields a much less readable code IMO, and that's one of the benefits of using operator << for output semantics.
Next look at the function's parameters. The first parameter, a std::ostream, is taken by reference. This so you can change the stream. That's also why the stream is not taken by const reference.
The second parameter can be taken by const reference, because we don't want to change it, just read it. However, we do want to take it by reference, again because we don't intend to change it, not even for a local purpose, and so saving the construction of a copy can only be a good idea. It also allows for accepting derivatives of Telegram and caling virtual functions upon them, should the need arise. Also, taking a const reference allows you to output a temporary, as in std::cout << Telegram() << '\n';.
{
os << "time: " << t.DispatchTime << " Sender: " << t.Sender
<< " Receiver: " << t.Receiver << " Msg: " << t.Msg;
This code should be self explanatory now. Presumably each of the members you insert into the output stream has the insertion operator defined for. The standard library defines insertion into output streams for primitives, for strings, for complex numbers and other standard types.
return os;
}
And finally you return the stream object, so the caller can chain the output with outputting another object. Note that you could simply return the result of the chain:
return os << "time: " << t.DispatchTime << " Sender: " << t.Sender
<< " Receiver: " << t.Receiver << " Msg: " << t.Msg;
Finally, to demonstrate the bonus you get from the use of a free function and taking the Telegram parameter by reference, consider:
struct Telegram {
Telegram();
Telegram(const Communication& c);
virtual ~Telegram();
};
struct Message : public Telegram {
};
struct Letter {
operator Telegram() const;
};
// ...
Telegram t;
Communication c;
Message m;
Letter l;
std::cout << t << '\n'
<< c << '\n'
<< m << '\n'
<< l << '\n';
All using that single function for outputting a Telegram object.