The syntax is in fact part of the new C++ standard, C++11. The rest of your code is compatible with the old standard, so you probably want to avoid using it. When I compile with g++ 4.4 and g++ 4.6, I get this warning by default:
Code:
templated.cpp: In function ‘foowrapper<T> print(const foo<T>&)’:
templated.cpp:17:5: warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x [enabled by default]
When I actually enable all warnings, I get more information:
Code:
$ g++ -Wall -Wextra templated.cpp -o templated
templated.cpp: In function ‘foowrapper<T> print(const foo<T>&)’:
templated.cpp:17:5: warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x [enabled by default]
templated.cpp: In function ‘std::ostream& operator<<(std::ostream&, const foowrapper<T>&)’:
templated.cpp:22:1: warning: no return statement in function returning non-void [-Wreturn-type]
The no return statement warning is because you don't have "return lhs;" in that function. So chaining this function together with multiple << operators would fail -- you're probably lucky it didn't segfault when you tried to put an "std::endl" after your print() calls.
However... this is valid C++ (not using any C++11) and compiles without warnings:
Code:
$ cat templated.cpp
#include <iostream>
#include <string>
template <typename T> class foo {
public:
T id;
void setId(T iniName) {
id = iniName;
}
};
template <typename T> struct foowrapper {
foo<T> const & objFoowrapper;
};
template <typename T> foowrapper<T> print(foo<T> const & objprint) {
return (foowrapper<T>){objprint}; // note cast
}
template <typename T> std::ostream & operator<<(std::ostream & lhs, foowrapper<T> const & rhs) {
lhs << '[' << rhs.objFoowrapper.id << ']';
return lhs; // note return value
}
int main() {
foo<std::string> f;
f.setId("blah");
std::cout << print(f) << std::endl;
foo<int> g;
g.setId(147);
std::cout << print(g) << std::endl;
g.id *= 2;
std::cout << print(g) << std::endl;
}
$ g++ -Wall -Wextra templated.cpp -o templated
$
Of course, the more standard way to do this would be to create a constructor for foowrapper that takes a foo as a parameter. Then you can avoid the strange syntax
Code:
(foowrapper<T>){...}
altogether, and just say "return objprint;". This will automatically construct a foowrapper for you (unless the constructor is marked explicit, in which case you could say "return foowrapper<T>(objprint);".
My take on the problem: The functionality you're looking for is closely related to stream manipulators from the header file <iomanip>, e.g. "std::cout << std::hex << 55" will print 55 in hex, "std::cout << std::oct << 55" will print 55 in octal. I don't know precisely how these work but you could do something similar by introducing your own stream wrapper around std::cout (or around any standard stream, really).
So here's my quick example.
Code:
#include <iostream>
class Foo {
private:
int a, b, c;
public:
Foo(int a, int b, int c) : a(a), b(b), c(c) {}
int getA() const { return a; }
int getB() const { return b; }
int getC() const { return c; }
};
class FooStream {
public:
enum FooPrintingMode {
PRINT_NORMAL,
PRINT_DETAILED
};
private:
std::ostream &stream;
FooPrintingMode mode;
public:
FooStream(std::ostream &stream) : stream(stream), mode(PRINT_NORMAL) {}
// print normal types
// (this is specialized to print Foo below)
template <typename T>
FooStream &operator << (const T &data) {
stream << data;
return *this;
}
// handle std::ostream manipulators
// there are two others you need to supply to handle all cases, see
// c++ - std::endl is of unknown type when overloading operator<< - Stack Overflow
FooStream &operator << (std::ostream & (*m)(std::ostream &)) {
m(stream);
return *this;
}
// handle FooStream manipulators
FooStream &operator << (FooStream & (*m)(FooStream &)) {
return m(*this);
}
void setMode(FooPrintingMode mode) {
this->mode = mode;
}
};
// template specialization: how to print Foo
template <>
FooStream &FooStream::operator << <Foo>(const Foo &foo) {
switch(mode) {
case PRINT_NORMAL:
stream << foo.getA();
break;
case PRINT_DETAILED:
stream << "[foo " << static_cast<const void *>(&foo)
<< ' ' << foo.getA()
<< ',' << foo.getB()
<< ',' << foo.getC() << ']';
break;
}
return *this;
}
// functors to set the foo-printing mode
FooStream &normalFoo(FooStream &stream) {
stream.setMode(FooStream::PRINT_NORMAL);
return stream;
}
FooStream &detailedFoo(FooStream &stream) {
stream.setMode(FooStream::PRINT_DETAILED);
return stream;
}
int main() {
Foo one(1, 2, 3);
Foo two(11, 22, 33);
FooStream stream(std::cout);
stream << normalFoo << one << std::endl;
stream << detailedFoo << two << std::endl;
return 0;
}
Sorry it's so complicated, I went a little overboard. The part to handle std::ostream manipulators is so that you can use std::endl. The output is
Code:
1
[foo 0x7ffffb4c9a00 11,22,33]
i.e. "one" is printed with mode PRINT_NORMAL, and "two" is printed with mode PRINT_DETAILED. I guess real std::ostream manipulators behave a bit differently, since
Code:
std::cout << std::hex << 5;
std::cout << 6;
sets a "hex" property that disappears by the time the second cout statement is invoked, whereas my implementation will set a property of the stream that stays set... but that's a minor point I guess.
You probably won't want to use my code if you're not too familiar with this stuff but it might be interesting to look at. Also, I wanted to say hi to a fellow Canadian! I don't speak French unfortunately, but it's good to see some Canadians using this forum.