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;
}
Related
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
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.
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;
}
When I'm writing a function in a template class how can I find out what my T is?
e.g.
template <typename T>
ostream& operator << (ostream &out,Vector<T>& vec)
{
if (typename T == int)
}
How can I write the above if statement so it works?
Something like this:
template< class T >
struct TypeIsInt
{
static const bool value = false;
};
template<>
struct TypeIsInt< int >
{
static const bool value = true;
};
template <typename T>
ostream& operator << (ostream &out,Vector<T>& vec)
{
if (TypeIsInt< T >::value)
// ...
}
Since C++11 we have std::is_same:
if (std::is_same<T, int>::value) ...
It's implemented similar to the suggested trait TypeIsInt suggested in the other answers,
but with two types to be compared.
Define it explicitly, e.g.:
template <>
ostream& operator << (ostream &out,Vector<int>& vec)
{
}
Simplest, most general solution:
Just write a plain old overload of the function:
ostream& operator << (ostream &out,Vector<int>& vec)
{
// Your int-specific implementation goes here
}
This assumes that the int and non-int versions don't have much code in common, as you have to write two separate implementations.
IF you want to use one common implementation of the function, with just an if statement inside that differs, use Charles Bailey's implementation:
template< class T >
struct TypeIsInt
{
static const bool value = false;
};
template<>
struct TypeIsInt< int >
{
static const bool value = true;
};
template <typename T>
ostream& operator << (ostream &out,Vector<T>& vec)
{
if (TypeIsInt< T >::value) {
// your int-specific code here
}
}
In general, don't use typeid if you don't need to.
The easiest way is to provide a template specialisation:
#include <iostream>
#include <vector>
using namespace std;
template <typename T> struct A {
};
template <typename T >
ostream & operator <<( ostream & os, A<T> & a ) {
return os << "not an int" << endl;
}
template <>
ostream & operator <<( ostream & os, A<int> & a ) {
return os << "an int" << endl;
}
int main() {
A <double> ad;
cout << ad;
A <int> ai;
cout << ai;
}
This way.
ostream & operator << (ostream &out, Vector<int> const & vec)
{
// ...
}
The compiler will choose this function over the function template if you pass Vector<int>.
Edit: I found this article, which attempts to explain why to prefer overloading to template specialization.
TypeID is never a good idea. It relies on RTTI.
By the way here is your answer :http://www.parashift.com/c++-faq-lite/templates.html#faq-35.7
One more solution is:
if(std::is_same<T, int>::value)
//It is int
if (std::is_same<T, double>::value)
//It is double
if (std::is_same<T, long double>::value)
//It is long double
C++ templates don't work this way. The general idea of templates is express somethings which is common for a lot of different types. And in your case you should use template specialization.
template<class T> ostream& operator<< (ostream& out, const vector<T>& v)
{
// your general code for all type
}
// specialized template
template<> ostream& operator<< <int>(ostream& out, const vector<int>& vec)
{
// your specific to iny type code goes here
}
Then C++ compiler will call this function when you use int type and general implementation for any other type
std::vector<int> f(5, 5);
std::cout << f;