how to query if(T==int) with template class - c++

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;

Related

Overriding << operator for templated struct

numcpp.h file
#include "iostream"
namespace numcpp{
template<typename T>
struct Vector
{
std::vector<T> v;
};
template<typename T>
struct Matrix
{
std::vector<T> m;
//template<typename T>
friend std::ostream& operator << (std::ostream& out, const mf& mat);
};
typedef Vector<float> vf;
typedef Matrix<vf> mf;
}
I am trying to overload << operator for cout to be able to print mf. First I tried making the overloading function a friend that directly takes mf as argument. I did this because if I took Matrix as argument, I would need to deal with template and I don't know how to do that.
numcpp.cpp file
#include "numcpp.h"
namespace numcpp{
std::ostream& operator << (std::ostream& out, const mf& mat)
{
//overloaded out here
return out;
}
}
main.cpp
#include "iostream"
#include "numcpp.h"
int main()
{
numcpp::mf inputs;
// inputs is filled with random numbers here
std::cout << inputs;
}
But this gives an error identified mf is undefined in .h file in line friend std::ostream& operator << (std::ostream& out, const mf& mat);
So I ditched this approach and tried removing the friend function declaration from Matrix without changing the .cpp file. But now I get a different error saying no operator << matches these operands.
I think this is because the overload is done in numcpp namespace so it is not visible from main which is outside the namesapce.
What you normally want is to define a template in your header file. The definition needs to be available at the call-site to allow the compiler to make an instatiation of the template.
If possible, the easiest way is to put the definition in the class definition.
template<typename T>
struct Matrix
{
std::vector<T> m;
// using Matrix here is allowed and refers to the current instatiation, equivalent to writing Matrix<T>
friend std::ostream& operator << (std::ostream& out, const Matrix& mat) {
...
return out;
}
};
Try change your numcpp.h to
namespace numcpp{
template<typename T>
struct Vector
{
std::vector<T> v;
};
typedef Vector<float> vf;
template<typename T>
struct Matrix
{
std::vector<T> m;
//template<typename T>
inline friend std::ostream& operator << (std::ostream& out, const Matrix<vf>& mat);
};
inline std::ostream& operator << (std::ostream& out, const Matrix<vf>& mat)
{
//overloaded out here
return out;
}
typedef Matrix<vf> mf;
}
You are getting this error because mf was not declared when you trying to use it.
Also, you can add the body of the function directly in the definition to get rid of the inline.
The typedefs are not available inside the definition of your class Matrix. You can either declare the typedef before the class definition (#Alloces' answer) of just template the overloaded operator:
#include <vector>
#include <sstream>
#include <iostream>
namespace numcpp {
template<typename T>
struct Vector
{
std::vector<T> v;
};
template<typename T>
struct Matrix
{
std::vector<T> m;
template<typename K> // template parameter must not be named T
inline friend std::ostream& operator << (std::ostream& out, const Matrix<K>& mat);
};
template<typename K>
inline std::ostream& operator << (std::ostream& out, const Matrix<K>& mat)
{
return out << "Just a test";
}
typedef Vector<float> vf;
typedef Matrix<vf> mf;
}
int main() {
numcpp::mf inputs;
std::cout << inputs << "\n"; // Just a test
}

Check if an integer function [duplicate]

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;

SFINAE overload operator<< to call 'print' method if it exists

I've been trying to understand SFINAE and was trying to write a simple overloaded operator << that would call the 'print' method on any class that contains such a method. I read through the answers on the question Is it possible to write a template to check for a function's existence? and tried writing:
template<class T, class = decltype(void(std::declval<T>().print), std::true_type{})>
inline std::ostream &operator<<(std::ostream &out, const T &obj) {
obj.print(out); return out; }
and
template<class T, class = decltype(void(std::declval<T>().print(std::declval<std::ostream &>())), std::true_type{})>
inline std::ostream &operator<<(std::ostream &out, const T &obj) {
obj.print(out); return out; }
but this simply doesn't work -- the compiler seems to have no problem instantiating the template for any type, so gives slews of 'ambiguous overload' errors when I try to print things like string literals...
Your "function exists" expression is incorrect. Try this:
template <typename T,
typename = decltype(
void(std::declval<T>().print(std::declval<std::ostream&>())),
std::true_type{})> // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
std::ostream & operator<<(std::ostream & out, const T & obj)
{
obj.print(out);
return out;
}
You might also consider this alternative:
template <typename T>
auto operator<<(std::ostream & out, const T & obj)
-> decltype(obj.print(out), (void)0, out)
{
obj.print(out);
return out;
}
I don't understand what you've meant your second type parameter
class = decltype(void(std::declval<T>().print), std::true_type{})
to mean. What is this supposed to evaluate to?
I think you can make it work by using the following.
#include <iostream>
#include <type_traits>
template<typename T,
typename = decltype(std::declval<const T>().print(std::cout))>
std::ostream&
operator<<(std::ostream& out, const T& obj)
{
obj.print(out);
return out;
}
struct A
{
void
print(std::ostream& out) const
{
out << "A";
}
};
int
main()
{
A a {};
std::cout << "And the winner is: " << a << std::endl;
}
It will correctly output And the winner is: A but there are probably some corner cases I've overlooked.
The expression
decltype(std::declval<const T>().print(std::cout))
will evaluate to the return type of the print(std::ostream&) const member function if such function is declared and a type error otherwise.

C++ containers - list members if operator<< is defined for type?

I am sorry if this is a duplicate, I'm not quite sure what I'm looking for.
I've defined a:
template<class T>
::std::ostream& operator<<(::std::ostream& stream,const container<T>& list);
which can just say "container of length" (or something)
and it'd be really nice if this could list the contents of the container, if
::std::ostream& operator<<(::std::ostream& stream, const T&);
was defined. It may not always be declared however. This is something that would be known at compile time (provided the compiler could see a declaration, user error could mean it is never included)
Can this be done?
This is most certainly a duplicate, I can't be the first to want to do this but I'm not sure what I'd be searching for.
Any means to do this would be appreciated.
Note:
I did think about using a trait but (to copy and paste my comment):
I
s there a C++11 way? I thought about traits too but you can't give
int a trait, assuming false by default (unless a trait exists and is
true) is great, but you can't do primitive types, or types defined
from libraries, you can of course create an operator<< for them
Example
Imagine:
container<int> someints(10); /*10 ints*/
container<A> someAs(5); /*5 As*/
container<B> someBs(7); /*7 Bs*/
With:
/*Obviously << for ints is defined*/
ostream& operator<<(ostream& stream, const B& b) {
stream<<"Whatever a B wants to do";
return stream;
}
template<class T>
ostream& operator<<(ostream& stream, const container<T>& list) {
stream<<"A list of length "<<list.get_length();
/*magic - if there is a << for T*/
stream<<"\n";
for(int k=0;k!=list.get_length();k++) {
stream<<list[k]<<"\n";
}
/*end of magic*/
return stream;
}
Then:
cout<<someints; /*shows a list of ints*/
cout<<someAs; /*shows its a list of 5 things - but cannot list the contents obviously*/
cout<<someBs; /*Showws it's a list of 7 things - and like someints lists them*/
This can be done: you'd use std::enable_if<...> to choose which version of the code should be used based on a predicate using the output operator. Below is a demonstration doing just that. The feature test is a bit ugly but right now I don't see how to really improve it. See here for a live example.
#include <iostream>
#include <type_traits>
template <typename T>
struct container
{
container(T const& v): value(v) {}
T value;
};
template <typename T>
struct has_output_test {
template <typename S>
static std::true_type test(typename std::decay<decltype(
std::declval<std::ostream&>() << std::declval<S>())>::type*);
template <typename S>
static std::false_type test(void*, ...);
};
template <typename T>
struct has_output
: decltype(has_output_test<T>::template test<T>(
static_cast<std::ostream*>(0)))
{
};
template <typename T>
typename std::enable_if<has_output<T>::value, std::ostream&>::type
operator << (std::ostream& out, container<T> const& c)
{
return out << "container[" << c.value << "]";
}
template <typename T>
typename std::enable_if<!has_output<T>::value, std::ostream&>::type
operator << (std::ostream& out, container<T> const&)
{
return out << "container[unknown]";
}
struct foo {};
int main()
{
std::cout << "foo=" << container<foo>(foo()) << '\n';
std::cout << "int=" << container<int>(int()) << '\n';
}
Yes. Boost has a type trait for that. More details at has_left_shift.
Here is an outline of how to do it:
template<typename T>
struct Container
{
void out(std::ostream& os, boost::true_type) const
{ os << "Huzzah"; }
void out(std::ostream& os, boost::false_type) const
{ os << "Oops"; }
friend std::ostream& operator<<(std::ostream& os, Container const& that)
{
using ostreamable = boost::has_left_shift<std::ostream, T>;
static_assert(ostreamable::value, "Not streamable");
that.out(os, ostreamable());
return os;
}
};
The static_assert will make it so you cannot stream out the container if T is not streamable; remove it if you want to do something else at run time for a non-streamable T.

using nested-types of a template-class as template parameter

I want to implement a template function using nested-types of a template-class.
I have just read here that it is better to implement operator << as non-member and non-friend function. Therefore I decided to move functions toStream() and tableToStream() outside MyClass:
template <typename T>
class MyClass
{
public:
typedef boost::dynamic_bitset<> BoolTable;
typedef std::vector<T> MsgTable;
private:
BoolTable b_;
MsgTable m_;
public:
const BoolTable& getB() const { return b_; }
const MsgTable & getM() const { return m_; }
std::ostream& toStream (std::ostream& os) const
{
os <<"Bool: "; tableToStream (os, getB()); os <<'\n';
os <<"Msg:"; tableToStream (os, getM()); os <<'\n';
return os;
}
template <typename TABLE>
std::ostream& tableToStream (std::ostream& os, const TABLE& table) const
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
};
template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T> mc)
{
return mc.toStream(os);
}
It's easy to convert MyClass::toStream() into an operator << non-member and non-friend function:
template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T>& mc)
{
os <<"Bool: "; mc.tableToStream (os, mc.getB()); os <<'\n';
os <<"Msg:"; mc.tableToStream (os, mc.getM()); os <<'\n';
return os;
}
But I want to use solely operator << instead of calling MyClass::tableToStream():
template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T>& mc)
{
os <<"Bool: "<< mc.getB() <<'\n';
os <<"Msg:" << mc.getM() <<'\n';
return os;
}
For the function MyClass::tableToStream() I could use the following implementation, but this may mess the stream output because the function is too generic (any type can be TABLE).
template <typename TABLE>
std::ostream& operator << (std::ostream& os, const TABLE& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
Therefore, I want to restrict to the nested types of MyClass. Below is one of my attempts to convert MyClass::tableToStream() into a standard operator << non-member and non-friend function:
template <typename T, typename MyClass<T>::TABLE>
std::ostream& operator << (std::ostream& os, const TABLE& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
But the error is about typename MyClass<T>::TABLE.
Since you have clarified your question a lot, my first answer does not apply any more and I'll remove-edit it to give you something that might fit better:
Updated answer:
You want to constrain the template to accept only types that are typedeffed inside your MyClass template. Such constraints are usually achieved by application of SFINAE, especially by std::enable_if (or boost::enable_if, if your library lacks that part of C++11 support). Sadly, there is no traits like a is_typedeffed_inside that could be used for your case. It's even worse: there is no way to write such a trait just using the plain typedefs, since there is nothing special about being typedeffed inside a given class - the compiler has no way to determine (and is not interested in) if a given known type has some alias name for it somewhere.
But if your typedefs are just the ones you show in your question, I have good news for you: you need exactly two operator<< for that:
One for boost::dynamic_bitset<>, since that is the BoolTable for any MyClass instantiation.
Another one, templated, for std::vector<T>, since that is the MsgTable for each corresponding MyClass<T>.
The downside is, that with this templated operator<<, you'd be able to output any std::vector<FooBar>, even if FooBar is completely unrelated to any use of MyClass. But that holds for any other possible implementation of the proper operator<<'s - if there's no explicit restriction on the MSG parameter, there's no restriction on a FooBar making a std::vector<FooBar> a viable MyClass<MSG>::MsgTable.
My conclusion for your question: you wanted to have the operator<< for its convenient looks, since it is normally used for thet purpose. In your case, you can provide it for MyClass<MSG> objects, but there is no way to do so for the inner typedefs alone.
I'd implement it that way:
template <class MSG>
class MyClass {
/* ... */
public:
// instead of declaring op<< a friend, redirect to a method that has
// natural access to private members
std::ostream& printToStream(std::ostream& os) const
{
os << "Bool: ";
tableToStream (getB(), os);
os <<"\nMsg:";
tableToStream (getM(), os);
return os <<'\n';
}
private:
// make this one private so nobody can misuse it to print unrelated stuff
template <class Table>
static void tableToStream(Table const& table, std::ostream& os)
{
std::copy(begin(table), end(table), ostream_iterator(os, ", "));
}
};
template <typename MSG>
std::ostream& operator << (std::ostream& os, const MyClass<MSG>& mc)
{
return mc.printToStream(os);
}
Your original class is fine. It is true that if you want to have an operator << for writing to a stream that it should be a non-member non-friend function, like you have, but there is no reason that function can't call a public member function to do the work.
I finally found this similar question
In my case the solution is:
template <typename T>
std::ostream& operator << (std::ostream& os,
typename MyClass<T>::TABLE const& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
UPDATE: As #ArneMertz pointed out, the above function does not work.
Below is the complete code I have tested:
#include <ostream>
#include <boost/dynamic_bitset.hpp>
template <typename T>
class MyClass
{
public:
typedef boost::dynamic_bitset<> BoolTable;
typedef std::vector<T> MsgTable;
BoolTable b_;
MsgTable m_;
const BoolTable& getB() const { return b_; }
const MsgTable & getM() const { return m_; }
};
template <typename T>
std::ostream& operator << (std::ostream& os,
typename MyClass<T>::TABLE const& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T>& mc)
{
os <<"Bool: "<< mc.getB() <<'\n'; // <-- this line is OK because it
os <<"Msg: "<< mc.getM() <<'\n'; //uses boost operator<<
return os;
}
and the main function:
#include <iostream>
int main()
{
MyClass<int> var;
var.b_.push_back(true);
var.b_.push_back(false);
var.b_.push_back(true);
var.m_.push_back(23);
var.m_.push_back(24);
var.m_.push_back(25);
std::cout << var;
}
I believe you are confusing something. The typename is just to be able to seperate it from the other template-parameters. Try to rename it to
template <typename OS, typename MSG, typename MSGTable>
OS& operator << (OS& os, const MSGTable& table) const{}
and then use it like an object.
See here.