operator<< cannot use an IT member of its friend, array - c++

i suppose that, if i make operator<< a friend of
a data struct (array by name);
//Forward Declarations
template<typename S, typename T>
struct array;
template<typename U, typename V>
ostream& operator<< (ostream& ous, const array<U, V>& t);
then, i will be able to do something like this; inside the implementation of operator <<
//operator<< is a friend of struct array{} already
template<typename T, typename U>
ostream& operator<< (ostream& os, const array<T, U>& var){
if(var){
/*Error: 'IT' was not declared in this scope*/
for(IT it = var.data.begin(); it != var.data.end(); it++){
/*and i thought i need not redeclare IT before using it
since operator<< is a friend of array already*/
}
}
else{cout << "empty";}
return os;
}
Now, here is array's implementation:
/*explicit (full) specialization of array for <type, char>*/
template<>
template<typename Key>
struct array<Key, char>{
//data members
map<const Key, string> data;
typedef map<const Key, string>::iterator IT;
//member function
friend ostream& operator<< <>(ostream& ous, const array& t);
//other stuff/functions
};
lastly, the compiler is angry when i test-drove it like this;
void Test(){
array<int, char> out;
out[1] = "one"; //Never mind. this has been taken care of
out[2] = "two";
cout << out; //Error: 'IT' was not declared in this scope
}
Question:
what exactly am i doing wrong, or, why can't i dirrectly access and use
IT (a typedef within array), even after i had declared operator << (that requests IT)
as a friend of the array struct ?

Write
for( typename array<T, U>::IT it = var.data.begin(); it != var.data.end(); it++){
And change
typedef map<const Key, string>::iterator IT;
to
typedef typename std::map<const Key, string>::const_iterator IT;
Here is a demonstrative program where instead of the std::map I used std::array for simplicity. I think it can help you.
#include <iostream>
#include <array>
template <typename T, size_t N>
struct A
{
std::array<T, N> a;
typedef typename std::array<T, N>::const_iterator IT;
};
template <typename T, size_t N>
std::ostream & operator <<( std::ostream &os, const A<T, N> &a )
{
for ( typename A<T, N>::IT it = a.a.begin(); it != a.a.end(); ++it ) os << *it << ' ';
return os;
}
int main()
{
A<int, 10> a = { { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } } };
std::cout << a << std::endl;
return 0;
}
The program output is
0 1 2 3 4 5 6 7 8 9

When you're using IT inside your template the compiler looks in the current scope (the operator template) for a declaration of a type named IT.
This fails because you defined the type as part of your array struct.
So in order to use the IT type you need to fully qualify it by using array<T,U>::IT.
Or you could try auto instead if you're using C++11.

Related

How to type custom io manipulators for use with const objects?

I'm trying to lift a simple Array-io manipulator I wrote to use std::vectors. Here is the old signature I had been using:
template<typename T>
struct arr {
const size_t size;
T* values;
arr(const size_t size, T* values) : size(size), values(values) {};
friend std::ostream& operator<<(std::ostream& os, const arr<T>& array);
friend std::istream& operator>>(std::istream& is, arr<T>& array);
};
Now I tried to lift it like so:
template<typename T>
struct arr {
std::vector<T>& vec;
arr(std::vector<T>& vec) : vec(vec) {};
friend std::ostream& operator<<(std::ostream& os, const arr<T>& array);
friend std::istream& operator>>(std::istream& is, arr<T>& array);
};
However I am facing the following problem: I want to use << arr(member) from inside a const declared member method. This doesnt't compile of course:
error: binding reference of type ‘std::vector<std::unique_ptr<IController> >&’ to ‘const std::vector<std::unique_ptr<IController> >’ discards qualifiers
However when I change the constructor aguments and arr::vec to const std::vector<T>& I have the opposite problem and >> arr(member) cannot work anymore!
I was hoping that by initializing the arr instance as const I could solve this but I face the same compiler error with the following line:
const streamutils::arr<int> list(myVector);
How can I solve this without declaring two different types for the in and out directions?
I attempted to look at the libstdc++ source to see how it is done for std::quoted but I couldn't figure it out.
You can parametrize your manipulator not with T but with vector<T> itself. This way you'll be able not to bother about your vector being const or not. Also create a helper function which returns the instance of your class with corresponding template type.
template<typename T>
using is_vector = std::is_same<T, std::vector<typename T::value_type, typename T::allocator_type>>;
template<typename T>
struct Arr {
static_assert(is_vector<std::decay_t<T>>::value);
T& vec;
// Note that arr is passed by value here because it is a temporary
// in expressions like 'cin >> arr(a)'
template<typename U>
friend std::enable_if_t<!std::is_const_v<U>, std::istream&> operator>>(std::istream& in, Arr<U> Arr);
template<typename U>
friend std::ostream& operator<<(std::ostream& out, const Arr<U>& Arr);
};
template<typename T>
std::enable_if_t<!std::is_const_v<T>, std::istream&> operator>>(std::istream& in, Arr<T> arr) {
int n;
in >> n;
arr.vec.resize(n);
for (int i = 0; i < n; ++i) {
in >> arr.vec[i];
}
return in;
}
template<typename T>
std::ostream& operator<<(std::ostream& out, const Arr<T>& arr) {
out << arr.vec.size() << "\n";
for (const auto& x: arr.vec) {
out << x << " ";
}
out << "\n";
return out;
}
template<typename T, typename = typename is_vector<std::decay_t<T>>::type>
Arr<T> arr(T& t)
{
return Arr<T>{t};
}
int main() {
vector<int> a;
cin >> arr(a);
cout << arr(a) << endl;
const vector<int> b{1, 2, 3};
cin >> arr(b); // compile error
cout << arr(b) << endl;
}
Also, consider reading this post, it explains various ways to make friend template operators (the one I showed here is not the best and not the only possible).

Overloading ostream of vector template with iterator

Why I can't use iterator in ostream overloading?
If I use the same declaration using iterative approach it works.
Consider the following code:
template <class T>
class List {
template <class U>
friend ostream &operator<<(ostream &os, const List<U> &rhs);
private:
vector<T> v;
};
template<class U>
ostream & operator<<(ostream & os, const List<U>& rhs)
{
vector<U>::iterator it = rhs.v.begin();
return os;
}
int main()
{
List<int> list;
cout << list << endl;
return 0;
}
Note that rhs is declared as reference to const, then rhs.v will be const too, then rhs.v.begin() will return a std::vector<U>::const_iterator, which can't be converted to std::vector<U>::iterator directly.
You should use typename for dependent type names.
So change it to
typename vector<U>::const_iterator it = rhs.v.begin();
BTW: void main() should be int main().
Try with
typename vector<U>::const_iterator it = rhs.v.begin();
If your rsh is const, you should use a const_iterator

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;

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.

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

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;