What is the best way to make a program that reads the elements from the input until the EOF and returns the container of read elements? This is what I have to do
p.h file:
#pragma once
#include <list>
#include <iostream>
typedef double Element;
template<typename T>
std::list<T> read(std::istream& u);
This is what I tried:
#pragma once
#include <list>
#include <iostream>
typedef double Element;
template<typename T>
std::list<T> read(std::istream& u){
while(u){
std::list<T> l;
l.push_front(u);
return l;
}
}
p.cpp file:
#include "p.h"
#include <iostream>
int main(){
double u;
std::cin>>u;
std::list<double> l=read(u);
}
What exactly do I have to pass as an argument the a main function? I tried passing an std::cin but it doesn't work. It could also be because read function is not defined properly.
Also I don't understand what's the point of typedef being double if we are making generic functions.
When you do l.push_front(u) you are trying to store the istream in the list. You need to read a T from the stream and store that instead. Also note that you need to declare l outside the loop in order to be able to read all values and then return l:
template<typename T>
std::list<T> read(std::istream& u){
T tmp;
std::list<T> l;
while(u >> tmp){
l.push_front(tmp);
}
return l;
}
Then specify the type you want to read from the stream by supplying it as a template parameter:
int main(){
auto l=read<double>(std::cin);
}
Related
The following codes come from an example code to illustrate how to use boost::type_traits. It will use two methods to swap two variables. It is easy to understand that when the two variables are integer (int) their type traits correspond to true_type. However, when two variables are bool type they are not regarded as true_type any more. Why would it happen? Thanks.
#include <iostream>
#include <typeinfo>
#include <algorithm>
#include <iterator>
#include <vector>
#include <memory>
#include <boost/test/included/prg_exec_monitor.hpp>
#include <boost/type_traits.hpp>
using std::cout;
using std::endl;
using std::cin;
namespace opt{
//
// iter_swap:
// tests whether iterator is a proxying iterator or not, and
// uses optimal form accordingly:
//
namespace detail{
template <typename I>
static void do_swap(I one, I two, const boost::false_type&)
{
typedef typename std::iterator_traits<I>::value_type v_t;
v_t v = *one;
*one = *two;
*two = v;
}
template <typename I>
static void do_swap(I one, I two, const boost::true_type&)
{
using std::swap;
swap(*one, *two);
}
}
template <typename I1, typename I2>
inline void iter_swap(I1 one, I2 two)
{
//
// See is both arguments are non-proxying iterators,
// and if both iterator the same type:
//
typedef typename std::iterator_traits<I1>::reference r1_t;
typedef typename std::iterator_traits<I2>::reference r2_t;
typedef boost::integral_constant<bool,
::boost::is_reference<r1_t>::value
&& ::boost::is_reference<r2_t>::value
&& ::boost::is_same<r1_t, r2_t>::value> truth_type;
detail::do_swap(one, two, truth_type());
}
}; // namespace opt
int cpp_main(int argc, char* argv[])
{
//
// testing iter_swap
// really just a check that it does in fact compile...
std::vector<int> v1;
v1.push_back(0);
v1.push_back(1);
std::vector<bool> v2;
v2.push_back(0);
v2.push_back(1);
opt::iter_swap(v1.begin(), v1.begin()+1);
opt::iter_swap(v2.begin(), v2.begin()+1);
return 0;
}
You've got the answer there in your code (as a comment):
See is both arguments are non-proxying iterators
vector<bool> has proxy iterators, because you can't refer directly to a bit.
If vector<bool> stored its' elements as individual booleans (taking 1-4 bytes/entry, depending on the system), the iterators could be non-proxying. But instead, vector<bool> stores 8 entries/byte and uses proxy iterators.
I have the following peaces of code:
// A.hpp
#include <vector>
namespace M {
struct A {
template <typename T>
A& operator>> (std::vector<T> &t) {
for (int i = 0; i < 4; ++i) {
t.push_back(T());
*this >> t.back();
}
return *this;
}
template <typename T>
A& operator>> (T &t) {
long long int v = 0;
t = static_cast<T>(v);
return *this;
}
};
}
// B.hpp
#include "A.hpp"
#include <tuple>
namespace N {
struct X { };
M::A& operator>> (M::A &b, X &x);
void f ();
}
// B.cpp
#include "B.hpp"
#include <tuple>
#include <vector>
#include <iostream>
namespace N {
M::A& operator>> (M::A &a, std::tuple<int, double> &v) {
return a;
}
struct Y { };
M::A& operator>> (M::A &a, Y &y) {
return a;
}
M::A& operator>> (M::A &a, X &x) {
// std::vector<std::tuple<int, double>> v2;
std::vector<Y> v2;
a >> v2;
return a;
}
void f () {
M::A a;
X x;
a >> x;
}
}
And to run the above I simply do:
N::f();
This is all about overloading the >> operator to be able to read vectors (this is simplified code, but it is complete enough to show the problem).
The above code will compile and work as expected, but if I uncommented the commented line in B.cpp and comment the line below:
std::vector<std::tuple<int, double>> v2;
// std::vector<Y> v2;
It does not compile because the overload of operator>> for std::tuple<int, double> is not found and it tries to call the templated method and of course fails to compile t = static_cast<T>(0).
I thought that maybe the compiler is not able to make the link between the two declaration of std::tuple<int, double> so I tried with a typedef but it changed nothing.
Why is it possible to overload the >> operator for a custom type (e.g. Y) but not for a standard std::tuple? Is there a way to overload the function for std::tuple?
Side-note: This is a quite complex MVCE but I am not able to reproduce the problem if I put everything in a single file... Feel free to edit if you come up with a smaller example.
My knowledge of the standard is a bit fuzzy, so please correct me if I'm wrong in some of my assumptions.
It seems that the compiler looks for the operator in the namespaces to which the arguments belong (preferred) and in the enclosing namespaces.
M::A& operator>> (M::A &a, Y &y) {
return a;
}
This operator is declared within the same namespace as the Y struct so it works.
M::A& operator>> (M::A &a, std::tuple<int, double> &v) {
return a;
}
This one is declared in the namespace N whereas its arguments belong to namespaces M and std, which means that the compiler will look in those namespaces and in the enclosing (global) namespace. If you move it into one of those, it works. For example, in B.cpp:
namespace M {
M::A& operator>> (M::A &a, std::tuple<int, double> &v) {
std::cout << "special call T" << std::endl;
return a;
}
}
I have no idea why it is allowed to declare the operator in a third-party namespace, so to speak, in the first place.
I have a piece of code to use the RTTI as case selector
#include <iostream>
#include <vector>
#include <typeinfo>
#include <complex>
#include <algorithm>
using namespace std;
typedef complex<int> data;
typedef std::vector< data > List;
template <typename T> void zeros(T &v)
{
if (typeid(typename T::value_type)==typeid(complex<int>))
std::fill(v.begin(), v.end(), complex<int>(0, 0));
else std::fill(v.begin(), v.end(), static_cast<typename T::value_type>(0));
}
int main(int argc, char *argv[])
{
List A;
zeros(A);
return 0;
}
In above code, I use typename T::value_type to determine the data type of the list, if there is complex then I will fill the list with complex zero. Otherwise, make it zero of the corresponding type. In above code, if I set data to be int, it does compile and run without any problem. But if I set it another other type, it fail to compile. I wonder if there is any way to make above code work for different type of data (for float, double, long, int, complex, complex and complex).
p.s. the reason I want to fill the vector in two cases because I am going to create my own complex for some reason and I have to tell the code how to create the complex zero or real zero. But for testing, I can't even make it work with built-in datatype
It seems that you want both a default initialized complex (0, 0), and a zero initialized int. You can achieve this using value initialization:
template <typename T> void zeros(T &v)
{
std::fill(v.begin(), v.end(), typename T::value_type{});
}
If you really want to perform some branching depending on what is T::value_type, then it would be better to use some type trait, like the following one:
template<typename T>
struct default_value {
static const T value;
};
template<>
struct default_value<std::complex<int>> { // assuming you'll use other complex type
static const std::complex<int> value;
};
template<typename T>
const T default_value<T>::value = T{};
const std::complex<int> default_value<std::complex<int>>::value = std::complex<int>(0, 0);
// now use it
template <typename T> void zeros(T &v)
{
std::fill(v.begin(), v.end(), default_value<typename T::value_type>::value);
}
But again, default construction and value initialization for built in types should be enough.
I have constructed a minimal working example to show a problem I've encountered using STL iterators. I'm using istream_iterator to read floatss (or other types) from a std::istream:
#include <iostream>
#include <iterator>
#include <algorithm>
int main() {
float values[4];
std::copy(std::istream_iterator<float>(std::cin), std::istream_iterator<float>(), values);
std::cout << "Read exactly 4 floats" << std::endl; // Not true!
}
This reads all possible floatss, until EOF into values, which is of fixed size, 4, so now clearly I want to limit the range to avoid overflows and read exactly/at most 4 values.
With more "normal" iterators (i.e. RandomAccessIterator), provided begin+4 isn't past the end you'd do:
std::copy(begin, begin+4, out);
To read exactly 4 elements.
How does one do this with std::istream_iterator? The obvious idea is to change the call to std::copy to be:
std::copy(std::istream_iterator<float>(std::cin), std::istream_iterator<float>(std::cin)+4, values);
But (fairly predictably) this doesn't compile, there are no candidates for operator+:
g++ -Wall -Wextra test.cc
test.cc: In function ‘int main()’:
test.cc:7: error: no match for ‘operator+’ in ‘std::istream_iterator<float, char, std::char_traits<char>, long int>(((std::basic_istream<char, std::char_traits<char> >&)(& std::cin))) + 4’
Any suggestions? Is there a correct, "STLified" pre-C++0x way to achieve this? Obviously I could just write it out as a for loop, but I'm looking to learn something about the STL here. I half wondered about abusing std::transform or std::merge etc. to achieve this functionality somehow, but I can't quite see how to do it.
Take a look at std::copy_n
As you requested a non-C++0x solution, here's an alternative that uses std::generate_n and a generator functor rather than std::copy_n and iterators:
#include <algorithm>
#include <string>
#include <istream>
#include <ostream>
#include <iostream>
template<
typename ResultT,
typename CharT = char,
typename CharTraitsT = std::char_traits<CharT>
>
struct input_generator
{
typedef ResultT result_type;
explicit input_generator(std::basic_istream<CharT, CharTraitsT>& input)
: input_(&input)
{ }
ResultT operator ()() const
{
// value-initialize so primitives like float
// have a defined value if extraction fails
ResultT v((ResultT()));
*input_ >> v;
return v;
}
private:
std::basic_istream<CharT, CharTraitsT>* input_;
};
template<typename ResultT, typename CharT, typename CharTraitsT>
inline input_generator<ResultT, CharT, CharTraitsT> make_input_generator(
std::basic_istream<CharT, CharTraitsT>& input
)
{
return input_generator<ResultT, CharT, CharTraitsT>(input);
}
int main()
{
float values[4];
std::generate_n(values, 4, make_input_generator<float>(std::cin));
std::cout << "Read exactly 4 floats" << std::endl;
}
If you wanted to, you could then use this generator in conjunction with boost::generator_iterator to use the generator as an input iterator.
If you don't have std::copy_n available, it's pretty easy to write your own:
namespace std_ext {
template<class InputIterator, class Size, class OutputIterator>
OutputIterator copy_n(InputIterator first, Size n, OutputIterator result) {
for (int i=0; i<n; i++) {
*result = *first;
++result;
++first;
}
return result;
}
}
We've been bitten by the following bug many times:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void print(int* pn) { cout << *pn << " "; }
int main() {
int* n1 = new int(1);
int* n2 = new int(2);
int* n3 = new int(3);
vector<int*> v;
v.push_back(n1);
v.push_back(n2);
v.push_back(n3);
sort(v.begin(), v.end()); // Here be dragons!
for_each(v.begin(), v.end(), print);
cout << endl;
delete n1; delete n2; delete n3;
}
The problem is that std::sort is comparing integer pointers not integers, which is not what the programmer intended. Worse, the output may appear correct and deterministic (consider the order of addresses returned by new or allocated on the stack). The root problem is that sort eventually calls operator< for T, which is rarely a good idea when T is a pointer type.
Is there any way to prevent this or at least get a compiler warning? For example, is there a way to create a custom version of std::sort that requires a comparison function when T is a pointer?
IMO, the programmers should know that std::sort assumes the container stores values. If you need a different behavior for the comparison, then you provide a comparison function. E.g. (untested):
template<typename T>
inline bool deref_compare(T* t1, T* t2) { return *t1 < *t2; }
//...
std::sort(v.begin(), v.end(), deref_compare<int>);
Edit
FWIW, Jacob's answer comes closest to directly accomplishing what you want. There might be some ways to generalize it further.
For pointers in general you could do this:
#include <ctime>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <functional>
#include <type_traits>
namespace util {
struct sort_pointers {
bool operator() ( int *a, int *b ) {
return *a < *b;
}
};
template <typename T, bool is_pointer = !std::tr1::is_pointer<T>::value>
struct sort_helper {
typedef std::less<T> wont_compare_pointers;
};
template <typename T>
struct sort_helper<T,false> {
};
template <typename Iterator>
void sort( Iterator start, Iterator end )
{
std::sort( start,
end,
sort_helper
<
typename Iterator::value_type
>::wont_compare_pointers() );
}
template <typename Iterator, class Func>
void sort( Iterator start, Iterator end, Func f ) {
std::sort( start, end, f );
}
}
int main() {
std::vector<int> v1;
std::vector<int*> v2;
srand(time(0));
for( int i = 0; i < 10; ++i ) {
v1.push_back(rand());
}
util::sort( v1.begin(), v1.end() );
for( int i = 0; i < 10; ++i ) {
v2.push_back(&v1[i]);
}
/* util::sort( v2.begin(), v2.end() ); */ //fails.
util::sort( v2.begin(), v2.end(), util::sort_pointers() );
return 0;
}
std::tr1::is_pointer was just what it was called in Visual Studio 2008, but I think Boost has one too, and newer compiles might provide it as std::is_pointer. I'm sure someone would be able to write a prettier solution, but this appears to work.
But I must say, I agree with cogwheel, there is no reason for this, the programmer should be able to see if this is going to be a problem and act accordingly.
Addition:
You can generalize it a bit more I think, to automatically select a functor that will dereference the pointers and compare the values:
namespace util {
template <typename T>
struct sort_pointers {
bool operator() ( T a, T b ) {
return *a < *b;
}
};
template <typename T, bool is_pointer = !std::tr1::is_pointer<T>::value>
struct sort_helper {
typedef std::less<T> compare;
};
template <typename T>
struct sort_helper<T,false> {
typedef sort_pointers<T> compare;
};
template <typename Iterator>
void sort( Iterator start, Iterator end )
{
std::sort( start,
end,
sort_helper
<
typename Iterator::value_type
>::compare() );
}
}
That way you don't have to think about if you're providing it with pointers to compare or not, it will automatically be sorted out.
I don't have a good answer for pointers in general, but you can restrict comparisons if you're using a smart pointer of any kind - eg boost::shared_ptr.
#include <boost/shared_ptr.hpp>
using namespace std;
template<class T>
bool operator<(boost::shared_ptr<T> a, boost::shared_ptr<T> b)
{
return boost::shared_ptr<T>::dont_compare_pointers;
}
int main () {
boost::shared_ptr<int> A;
boost::shared_ptr<int> B;
bool i = A < B;
}
Output:
In function 'bool operator<(boost::shared_ptr<T>, boost::shared_ptr<T>) [with T = int]':
t.cpp:15: instantiated from here
Line 8: error: 'dont_compare_pointers' is not a member of 'boost::shared_ptr<int>'
compilation terminated due to -Wfatal-errors.
So you can use smart pointers, or create your own smart pointer wrapper. This is very heavyweight for what you want though, so if you do create a wrapper to detect this situation, I recommend you only use it in debug mode. So create a macro (ugh, I know) and use it to declare pointers.
#ifdef DEBUG
#define pointer(x) pointer_wrapper<X>
#else
#define pointer(x) x*
#endif
This still requires your programmers to use it, of course!