I want to do something like this:
#include <iostream>
template<typename T>
class myclass
{
T something;
public:
myclass(T something) : something{ something }
{ }
struct result
{
T value;
};
result get_result()
{
return{ something };
}
};
template<typename T>
std::ostream& operator<<(std::ostream& stream, const typename myclass<T>::result& res)
{
return stream << res.value;
}
int main()
{
myclass<int> m(0);
std::cout << m.get_result() << "\n";
}
In this case neither gcc nor msvc find the overloaded stream operator when I put in a result (which is dependent on a templated outer class). Is what I am trying to do even possible?
T is non-deductible for myclass<T>::result.
You may define operator<< inside the class to solve your issue:
struct result
{
T value;
friend std::ostream& operator<<(std::ostream& stream, const result& res)
{
return stream << res.value;
}
};
Demo
Related
I have this data and operator defined in namespace a:
namespace a {
enum class E {
VALUE
};
std::ostream& operator<<(std::ostream& os, const E e)
{
return os << "VALUE";
}
}
My code operates in namespace b, and it would like to use another operator<< for the same type, replacing the one originally defined in namespace a:
namespace b {
std::ostream& operator<<(std::ostream& os, const a::E e)
{
return os << "value";
}
void f()
{
const auto e = a::E::VALUE;
std::cout << e << std::endl;
}
}
int main()
{
b::f();
return 0;
}
Because of ADL, compiler get confused and sees the call to operator<< as an ambiguous call, since both the namespace a and namespace b version are available.
How can I make it use my version of operator<< when user code is inside namespace b without ambiguity?
Another way:
namespace b {
template<class T>
struct Wrapper { T value; };
template<class T>
inline Wrapper<T> wrap(T t) {
return {t};
}
std::ostream& operator<<(std::ostream& os, Wrapper<a::E> e) {
return os << "value";
}
void f() {
const auto e = a::E::VALUE;
std::cout << wrap(e) << std::endl;
}
} // namespace b
Alternatively, with reusable Wrapper:
template<class Tag, class T>
struct Wrapper { T value; };
template<class Tag, class T>
inline Wrapper<Tag, T> wrap(T t) {
return Wrapper<Tag, T>{t};
}
namespace b {
struct Tag {};
std::ostream& operator<<(std::ostream& os, Wrapper<Tag, a::E> e) {
return os << "value";
}
void f() {
const auto e = a::E::VALUE;
std::cout << wrap<Tag>(e) << std::endl;
}
} // namespace b
To remove ambiguity, you might full qualify the call:
b::operator <<(std::cout, e) << std::endl;
Not really fine with operator though, I agree.
I have this snippet of code and I do not understand why the std::cout line is not compiling... The argument lookup / template argument inferencing seems correct...
#include <iostream>
template<typename T>
struct A
{
struct M1
{
T x;
};
};
template<typename T>
std::ostream &operator<<(std::ostream &os, typename A<T>::M1 const &o)
{
os << o.x;
return os;
}
int main()
{
A<int>::M1 a;
std::cout << a; // This line fails
return 0;
}
BTW I'm trying to do this without a declaring operator<<() as an inline function.
Your problem is that T is in a non deduced context. C++ will only simple pattern match, it will not invert possibly arbitrary type maps.
Imagine there was a specialization of A<void> that set using M1=A<int>::M1. Now both int and void are valid T for your <<. As the problem is intractible in general, C++ refuses to even try: you can only pattern match on direct template arguments of your argument types.
To do what you really want:
template<typename T>
struct A {
struct M1 {
T x;
friend std::ostream& operator<<(std::ostream& os, M1 const& m1){
return os << m1.x;
}
};
};
Learn to love Koenig operators.
The template parameter T of your operator cannot be deduced. However, there is some workaround using some SFINAE magic:
#include <iostream>
template<typename T>
struct A {
struct M1 {
using type = T;
T x;
};
};
template<typename T, std::enable_if_t<std::is_same<T, typename A<typename T::type>::M1>::value, int> = 0>
std::ostream &operator<<(std::ostream &os, const T& o)
{
os << o.x;
return os;
}
int main()
{
A<int>::M1 a;
std::cout << a; // This line works
return 0;
}
I'm working on a tiny compiler, and I use boost::variant<bool, ClassA> infoto store the information of each node.
boost::variant will automatically call the correct << operator of a specific type when I call std::cout<< node.info;
However, since the built-in formatting function of ostream doesn't satisfy my requirement(print #t instead of 1 if node.info==true and print "string" instead of string), new types of bool/string should be introduced.
I want to implement a template class Wrapper<T>, which behaves just like T(because there are lots of old code) and provides the interface of <<.
At first, the following version was implemented:
template<typename T> class Wrapper : public T
{
public:
template<typename ... U> Wrapper(const U& ... a):T(a...) {}
friend std::ostream& operator <<(std::ostream& o, const Wrapper<T>& w);
};
This version works well for std::string, but when T=bool, since built-in types cannot be inherited, an error will raise.
My current workaround is to use partial specialization:
template<typename T, bool ISCLASS= std::is_class<T>::value> class Wrapper;
template<typename T> class Wrapper<T, false>
{
private:
T inner;
public:
template<typename ... U> Wrapper(const U& ... a): inner(a...) {}
//Wrap the operators (= + += ...)
template<typename U> Wrapper<T> operator !() { Wrapper<T> res(*this); res.inner=!res.inner; return res; }
operator T() const{ return inner; }
friend std::ostream& operator <<(std::ostream& o, const Wrapper<T>& w);
};
template<typename T> class Wrapper<T, true> : public T
{
public:
template<typename ... U> Wrapper(const U& ... a):T(a...) {}
friend std::ostream& operator <<(std::ostream& o, const Wrapper<T>& w);
};
Obviously it is not a perfect solution because I have to wrap every operators of bool or any other built-in types.
Any help would be appreciated.
Thanks.
Could we consider something simpler?
Create a simple wrapper, using reference or pointer.
template <class T>
struct MyFormattingWrapper
{
const T& nucleus;
};
And then a factory function for it.
template <class T>
MyFormattingWrapper<T> my_formatting(const T& n)
{
return MyFormattingWrapper<T>{ n };
}
And then, you can specialize the formatting for each type.
std::ostream& operator << (std::ostream& o, const MyFormattingWrapper<int>& w)
{
return o << "int:" << w.nucleus;
}
std::ostream& operator << (std::ostream& o, const MyFormattingWrapper<std::string>& w)
{
return o << "std::string:" << w.nucleus;
}
int main()
{
std::cout << my_formatting(123) << std::endl;
std::cout << my_formatting(std::string{ "abc" }) << std::endl;
}
Update:
C-string may be a special case. But it is not difficult.
struct MyFormattingWrapper_c_string
{
const char* const nucleus;
};
MyFormattingWrapper_c_string my_formatting(const char* n)
{
return MyFormattingWrapper_c_string{ n };
}
MyFormattingWrapper_c_string my_formatting(char* n)
{
return MyFormattingWrapper_c_string{ n };
}
std::ostream& operator << (std::ostream& o, const MyFormattingWrapper_c_string& w)
{
return o << "c-string:" << w.nucleus;
}
Nicky C's answer is great, but has an issue with partial specialization of functions not being OK. This means you can't produce a version that works on general vectors like this:
template<typename T>
std::ostream& operator << (std::ostream& o, const MyFormattingWrapper<std::vector<T>>& vec)
{
o << "vec:[ "
for(auto v : vec) {
o<<my_formatting(v);
o<<" ";
}
return o<<"]"
}
You can get around this by putting the core of the specialized output into the MyFormattingWrapper classes and having only one operator<<
// The default one
template <class T> struct MyFormattingWrapper {
const T& nucleus;
ostream& output(ostream & os) {
return os<<nucleus;
}
};
// Specialized for string
template <> struct MyFormattingWrapper<std::string> {
const std::string& nucleus;
ostream& output(ostream & os) {
return os<<"string:"<<nucleus;
}
};
// Specialized for vector
template <class T> struct MyFormattingWrapper<std::vector<T>> {
const std::vector<T>& nucleus;
ostream& output(ostream & os) {
os<<"vec:[";
for(auto & v: nucleus) {
os<<my_formatting(v)<<" ";
}
return os<<"]";
}
};
// Now there's just one of these, so partial template
// specialization doesn't cause us any problems
template<typename T>
std::ostream& operator << (std::ostream& os, const MyFormattingWrapper<T>& w) {
return w.output(os);
}
Perhaps I better make the follow-up regarding boost::variant another answer.
Firstly, learning from #MichaelAnderson, and considering the interoperability with boost::variant, I would like to improve the design of the wrapper. We add a constructor to enable type conversion for from the nucleus type to the wrapper type.
template <class T>
class MyFormatting;
template <class T>
MyFormatting<T> my_formatting(const T& n)
{
return MyFormatting <T>{n};
}
// int
template <>
class MyFormatting<int>
{
private:
const int& nucleus;
public:
MyFormatting(const int& n) : nucleus(n) {}
friend std::ostream& operator << (std::ostream& os, const MyFormatting& w)
{
return os << "int:" << w.nucleus;
}
};
// std::string
template <>
class MyFormatting<std::string>
{
private:
const std::string& nucleus;
public:
MyFormatting(const std::string& n) : nucleus(n) {}
friend std::ostream& operator << (std::ostream& os, const MyFormatting& w)
{
return os << "std::string:" << w.nucleus;
}
};
// c-string
template <>
class MyFormatting<char*>
{
private:
const char* nucleus;
public:
MyFormatting(const char* n) : nucleus(n) {}
friend std::ostream& operator << (std::ostream& os, const MyFormatting& w)
{
return os << "c-string:" << w.nucleus;
}
};
MyFormatting<char*> my_formatting(const char* n)
{
return MyFormatting<char*>{n};
}
// std::vector
template <class T>
class MyFormatting<std::vector<T>>
{
private:
const std::vector<T>& nucleus;
public:
MyFormatting(const std::vector<T>& n) : nucleus(n) {}
friend std::ostream& operator << (std::ostream& os, const MyFormatting& w)
{
os << "std::vector:[";
for (const auto& x : w.nucleus)
{
os << x << " ";
}
os << "]";
return os;
}
};
Next, let's use the wrapper with boost::variant. The constructor of the wrapper enables conversion between variant of nuclues types to variant of the wrappers.
boost::variant<int, std::string> var_int = 50;
boost::variant<int, std::string> var_str = "fifty";
boost::variant<MyFormatting<int>, MyFormatting<std::string>> var_fmt_int = var_int;
boost::variant<MyFormatting<int>, MyFormatting<std::string>> var_fmt_str = var_str;
std::cout << var_int << " " << var_str << std::endl;
std::cout << var_fmt_int << " " << var_fmt_str << std::endl;
But boost::variant<MyFormatting<int>, MyFormatting<std::string>> spells too long. We can make it shorter.
template <class... T>
using Variant_Formatting_t = boost::variant < MyFormatting<T>... > ;
std::cout << Variant_Formatting_t<int, std::string>{var_int} << " " << Variant_Formatting_t<int, std::string>{var_str} << std::endl;
Since boost::variant use macro-template metaprogramming to emulate variadic template instead of using C++11 variadic template, I cannot make it cleaner using type deduction. This is the furthest I can get to.
My goal is to design a String class that decorates std::string in order to provide some functionality my program needs. One functionality I want to add is the ability to convert anything to my String implicitly in order to save some typing.
In order to achieve the implicitly conversion I designed the following class:
std::ostream& operator<<(std::ostream& o, const String& s);
class String {
public:
template<typename t_value>
String::String(t_value value) {
std::ostringstream oss;
oss << value;
_str = oss.str();
}
private:
std::string _str;
}
This works fine with any type that has the <<operator defined. The problem came up with any class that doesn't have the stream operator. A compiler error would be fine but what I got is an infinity recursion since C++ tries to use my global << operator to try to convert to my String type.
My primary objective is to code like this
class Foo {
int _memberWithUnderscoreInName;
}
String s = Foo();
And get a compiler error instead of an infinite loop in the constructor.
Is there a simple solution for this?
Instead of declaring the output operator in the surrounding namespace, only declare it as a friend of the String class:
class String {
public:
// This must be implemented inline here
friend std::ostream& operator<<(std::ostream& o, const String& s) {
return o << _str; // for example
}
template<typename t_value>
String(t_value value) {
std::ostringstream oss;
oss << value;
_str = oss.str();
}
private:
std::string _str;
};
Now it can only be found by argument-dependent lookup, and so will only be considered if the second argument really is of type String, not just convertible to it. Therefore, it won't be considered as a candidate for os << value in the constructor, giving a compile error rather than a run-time death spiral if there is no other candidate.
This or similar should fix it:
namespace HasFormattedOutput {
namespace Detail
{
struct Failure{};
}
template<typename OutputStream, typename T>
Detail::Failure operator << (OutputStream&, const T&);
template<typename OutputStream, typename T>
struct Result : std::integral_constant<
bool,
! std::is_same<
decltype((*(OutputStream*)0) << std::declval<T>()),
Detail::Failure
>::value
> {};
} // namespace HasFormattedOutput
template <typename T, typename OutputStream = std::ostream>
struct has_formatted_output
: HasFormattedOutput::Result<OutputStream, T>
{};
class X {
public:
X() {}
template <typename T>
X(const T& t) {
static_assert(
has_formatted_output<T>::value,
"Not supported type.");
std::ostringstream s;
s << t;
str = s.str();
}
private:
std::string str;
};
std::ostream& operator << (std::ostream& stream, const X&) { return stream; }
struct Y {
Y() {}
};
int main() {
Y y;
X x(y);
return 0;
}
I want to print state of my objects through toString member function, but I want to call it through String::toString(var). But I want to do this only for object, who doesn't have operator<< defined.
My attempt is below.
I have template operator<< which call toString, but I hoped that this operator will be taken into account only if no other suitable operator<< has been found. I was obviously wrong :)
#include <iostream>
#include <sstream>
struct WithToString
{
std::string toString()
{ return std::string ("foo") ; }
};
struct WithoutToString {};
struct String
{
template <typename T>
static std::string toString(T & var)
{
std::stringstream s;
s << var;
return s.str();
}
};
template <typename T>
std::ostream & operator<<(std::ostream & s, T & var)
{
s << var.toString();
return s;
}
int main(int argc, char *argv[])
{
int i = 5;
std::cout << String::toString(i); //fine, prints 5
WithToString w;
std::cout << String::toString(w); //fine, prints foo
// WithoutToString ws;
// std::cout << String::toString(ws); //fine - give "toString is not a member" error
// const char * s = "bar";
// std::cout << String::toString(s); //error - operator << is ambiguous
// std::string s = "bar";
// std::cout << String::toString(s); //error - toString is not a member
return 0;
}
How to achieve this behavior?
EDIT
here is my other attempt, but again fails with string and char *
template <class Type, class V>
class HasOperatorShiftLeft
{
template <typename T, T> struct TypeCheck;
typedef char Yes;
typedef long No;
template <typename T> struct ToString
{
typedef std::ostream & (T::*fptr)(V);
};
template <typename T> static Yes HasOpShift(TypeCheck< typename ToString<T>::fptr, &T::operator<< >*);
template <typename T> static No HasOpShift(...);
public:
static bool const value = (sizeof(HasOpShift<Type>(0)) == sizeof(Yes));
};
template <typename T, int A>
struct toStringStr{};
template <typename T>
struct toStringStr<T,1>
{
static std::string toString(T & var)
{
std::stringstream s;
s << var;
return s.str();
}
};
template <typename T>
struct toStringStr<T,0>
{
static std::string toString(T & var)
{
return var.toString();
}
};
template <typename T>
std::string toString(T & var)
{
return toStringStr<T,HasOperatorShiftLeft<std::ostream,T>::value>::toString(var);
}
EDIT
my newest attempt is posted as Answer, because I think, it works
This is actually pretty easy, albeit stupid to do as described in the comments. With C++11:
template<class T>
auto operator<<(std::ostream& os, T const& val)
-> decltype(os << val.toString())
{
return os << val.toString();
}
This function will only exist if what's inside decltype(..) is a valid expression. Now just stream everything into an std::ostream& and call it a day. If a type has both toString and and overloaded operator<< for std::ostream&, well, tough. You'll get an "ambiguous call to overloaded operator<<" error.
For C++03, there's another option. Since you seem to kinda dislike free functions, I'll assume you like interfaces. As such, get yourself a Streamable base class with a virtual std::string toString() const = 0 method and overload operator<< only for that. Presto, you have operator<< for all classes that implement that interface!
struct Streamable{
virtual std::string toString() const = 0;
};
std::ostream& operator<<(std::ostream& os, Streamable const& s){
return os << s.toString();
}
Or you can even go down to the meta level to get rid of the useless virtual function call:
template<class D>
struct Streamable{
std::string toString() const{
return static_cast<D const&>(*this).toString();
}
};
template<class D>
std::ostream& operator<<(std::ostream& os, Streamable<D> const& s){
return os << s.toString();
}
// example:
struct Blub
: public Streamable<Blub>
{
// implement toString() ...
};
What about this?
I think it works just fine...
struct String
{
template <typename T>
static std::string toString(const T & var)
{
std::stringstream s;
s << var;
return s.str();
}
};
template<typename Elem, typename Traits, typename T>
std::basic_ostream<Elem, Traits> & operator <<(std::basic_ostream<Elem, Traits> & s, const T & var)
{
s << var.toString();
return s;
}