What am I doing wrong with my bind function here? - c++

I wrote my bind function which returns a nullary functor because I don't have boost. Though this code compiles fine, it does not behave as I expected. When I input 2 as the number of numbers and try to enter them, the program terminates the first time I hit return. And, when I debug, it segfaults inside mem_fun_t::operator(). What am I doing wrong here? And how to rectify it?
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <iterator>
#include <functional>
using namespace std;
namespace MT
{
template<class Operation>
struct binder
{
protected:
Operation _op;
typename Operation::argument_type _arg;
public:
binder(Operation& fn, typename Operation::argument_type arg)
:_op(fn), _arg(arg)
{
}
typename Operation::result_type operator()()
{
return _op(_arg);
}
};
template<class Operation, class Arg>
binder<Operation> bind(Operation op, Arg arg)
{
return binder<Operation>(op, arg);
}
};
int main()
{
vector<int> vNumbers;
vector<char> vOperators;
int iNumCount = 0;
int iNumOperators = 0;
cout << "Enter number of number(s) :) :\n";
cin >> iNumCount;
int iNumber;
cout << "Enter the " << iNumCount << " number(s):\n";
generate_n(back_inserter(vNumbers), iNumCount, MT::bind(mem_fun(&istream::get), &cin));
system("clear");
copy(vNumbers.begin(), vNumbers.end(), ostream_iterator<int>(cout, " "));
cout << endl;
}

istream::get is not the right method to use, as it reads characters, not ints. You'd need to use operator>> (and selecting the right overload is very verbose), or just write a different functor:
template<class T>
struct Extract {
istream &stream;
Extract(istream &stream) : stream (stream) {}
T operator()() {
T x;
if (!(stream >> x)) {
// handle failure as required, possibly throw an exception
}
return x;
}
};
// ...
generate_n(back_inserter(vNumbers), iNumCount, Extract<int>(cin));

Related

How can one shorten the code when reading input?

int testcases;
cin >> testcases;
Is there a way to shorten the above to one line? Or more generally, can anyone provide me a good resource where I can read about code shortage that doesn't necessarily affect the readability?
There isn't a whole lot to shorten there; however if you were going to be writing many instances of the above, you could write a helper-function like this:
int readInt()
{
int i;
cin >> i;
return i;
}
... then your many instances could be just one line apiece:
int testcases = readInt();
Building on Jeremy's idea, you could make a function template that creates and reads into many variables at once:
#include <iostream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <utility>
template<class... Types, size_t... I>
void readthem(std::istream& is, std::tuple<Types...>& rv, std::index_sequence<I...>) {
// A C++17 fold expression
(is >> ... >> std::get<I>(rv));
}
template<class... Types, class Indices = std::make_index_sequence<sizeof...(Types)>>
auto readvars(std::istream& is) {
std::tuple<Types...> rv; // A tuple consisting of the types you want
readthem(is, rv, Indices{});
if(not is) throw std::runtime_error("Input failed");
return rv;
}
int main() {
// read an int, a double and a std::string
auto[i, d, s] = readvars<int, double, std::string>(std::cin);
std::cout
<< i << '\n'
<< d << '\n'
<< s << '\n';
}

Let ss be a std::stringstream. How to specify a concept for (ss<<some_type).str() is a std::string?

Let ss be a std::stringstream. How to specify a concept for (ss << some_type).str() is a std::string?
Here is the code I have so far:
#include <iostream>
#include <sstream>
namespace detail {
template< class T, class U >
concept SameHelper = std::is_same_v<T, U>;
}
template< class T, class U >
concept same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;
template<typename T>
concept ssToStr = requires(T a, std::stringstream ss) {
{ (ss << a).str() } -> same_as<std::string>;
};
void call(ssToStr auto obj)
{
std::stringstream ss;
std::cout << (ss << obj).str() << std::endl;
}
int main()
{
call("Hi");
return 0;
}
You can check online that the code does not compile.
The first part of the error messages reads:
<source>:25:5: error: no matching function for call to 'call'
call("Hi");
^~~~
You're missing #include <sstream>
Fixing that gives the error message that contains:
<source>:14:17: note: because '(ss << a).str()' would be invalid: no member named 'str' in 'std::basic_ostream<char>'
{ (ss << a).str() } -> same_as<std::string>;
Which tells you that (ss << obj) evaluates to a std::ostream, which does not have a .str() member. All you have to check is that ss<<a compiles, and you already know that ss.str() results in a string, so you don't need that in your constraint.
Unfortunately, I don't know enough about constraints to create the working code for you.
Thanks to Mooing Duck I was able to get the code running. The running code reads:
#include <iostream>
#include <sstream>
template<typename T>
concept ssToStr = requires(T a, std::stringstream ss) {
{ ss << a };
};
void call(ssToStr auto obj)
{
std::stringstream ss;
ss << obj;
std::cout << ss.str() << std::endl;
}
int main()
{
call("Hi");
return 0;
}
You can run the code online

C++ templated class default constructor fails

So I am creating a Stack class for an assignment in C++. The core of the assignment is to familiarize us with templates. I have read my book over and over and looked question after question on here.
I need to have my Stack class be able to be constructed by
Stack s2;
but I get an error when I compile my test.cpp and can only compile when i construct as
Stack<T> s1;
where T is a std::string, int, etc. How do build my Stack so I can use both constructors?
Stack.cpp
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
using namespace std;
template<typename T>
class Stack {
public:
Stack();
void Push(T val);
T Pop();
void Print();
private:
vector<T> vecT;
};
template <typename T>
Stack<T>::Stack() { }
template <typename T>
void Stack<T>::Push(T val) { vecT.push_back(val); }
template <typename T>
T Stack<T>::Pop() { vecT.pop_back(); }
template <typename T>
void Stack<T>::Print() {
cout << "[ ";
for(int i=0; i<vecT.size(); i++) {
cout << vecT[i] << " ";
}
cout << "]";
}
test.cpp
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
#include "Stack.cpp"
using namespace std;
int main() {
Stack<string> s1;
s1.Push("values1");
s1.Push("values2");
s1.Print();
Stack s2;
s2.Push("values1");
s2.Push("values2");
s2.Print();
}
What about a default template parameter?
template<typename T = std::string>
class Stack {
Anyway, with
Stack<T> s1;
and
Stack s2;
you're not using different constructors; you're using, in both cases, the same default (no arguments) constructor.
Instead of templating everything you could just use a stack of a variant type (since C++17, before use Boost.Variant). With the code below you can now push int, double, and std::string onto the stack. Furthermore, Pop() is missing a return statement. Also, pop_back() of vector returns nothing.
#include <iostream>
#include <vector>
#include <string>
#include <variant>
class Stack {
using Variant = std::variant<int,double,std::string>;
public:
Stack();
void Push(Variant val);
void Pop();
void Print();
private:
std::vector<Variant> vecT;
};
Stack::Stack() : vecT() {}
void Stack::Push(Variant val) { vecT.push_back(val); }
void Stack::Pop() { vecT.pop_back(); }
void Stack::Print() {
std::cout << "[ ";
for ( auto const& v : vecT )
std::visit([] (auto&& arg) { std::cout << arg << " "; }, v);
std::cout << "]\n";
}
int main() {
Stack s1;
s1.Push("values1");
s1.Push("values2");
s1.Print();
Stack s2;
s2.Push("values1");
s2.Push("values2");
s2.Print();
}
With Boost.Variant you get a C++98 compatible solution.
#include <iostream>
#include <vector>
#include <string>
#include <boost/variant.hpp>
class Stack {
typedef boost::variant<int,double,std::string> Variant;
typedef std::vector<Variant>::iterator Iterator;
std::vector<Variant> vecT;
struct visitor : public boost::static_visitor<void>
{
template < typename T >
void operator()(T const& arg) const { std::cout << arg << " "; }
};
public:
Stack();
void Push(Variant val);
void Pop();
void Print();
};
Stack::Stack() : vecT() {}
void Stack::Push(Variant val) { vecT.push_back(val); }
void Stack::Pop() { vecT.pop_back(); }
void Stack::Print() {
std::cout << "[ ";
for ( Iterator it = vecT.begin(); it != vecT.end(); ++it )
boost::apply_visitor( visitor(), *it );
std::cout << "]\n";
}
int main() {
Stack s1;
s1.Push("values1");
s1.Push("values2");
s1.Print();
Stack s2;
s2.Push("values1");
s2.Push("values2");
s2.Print();
}
You could use a default template parameter:
template<typename T = int>
class Stack {
Then you could construct using:
Stack<> s2;
Also, the constructors are identical, you aren't calling a different one each time, but rather the template argument differs.

How to convert std::string to any of several types in constructor?

I have the following class template which has a member variable whose type is determined by the template argument. I want to initialize the value of this member in the constructor, which only takes a std::string. Thus, my problem is that I need to convert std::string to any of several types (int, double, bool, string). I don't think I can specialize just the constructor, and I would rather not specialize the entire class for each type. The problem with my code below is that stringstream stops streaming out when it hits a space:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template <typename Ty>
struct Test
{
Ty value;
Test(string str) {
stringstream ss;
ss.str(str);
ss >> value;
}
};
int main()
{
Test<int> t1{"42"};
Test<double> t2{"3.14159"};
Test<string> t3{"Hello world"};
cout << t1.value << endl << t2.value << endl << t3.value << endl;
return 0;
}
The output of the above code is:
42
3.14159
Hello
instead of "Hello world". Is there some way to get stringstream to not stop at whitespace, or some other device that will do arbitrary conversions like I need?
This works for me. Just declare a special implementation before the generalized implementation:
#include <iostream>
#include <string>
#include <sstream>
template<typename T>
struct Test {
T value;
Test(std::string);
};
template<>
inline Test<std::string>::Test(std::string str) {
value = str;
}
template<typename T>
inline Test<T>::Test(std::string str) {
std::stringstream ss;
ss.str(str);
ss >> value;
}
int main() {
Test<int> t1{"42"};
Test<double> t2{"3.14159"};
Test<std::string> t3{"Hello world"};
std::cout
<< t1.value << std::endl
<< t2.value << std::endl
<< t3.value << std::endl;
return 0;
}
Here is an ideone working example.

How to call generic template function in a specialization version

Have a problem about how to call the generic template version in a specialization version.
Here is the sample code. But the "vector::push_back(a)" calls itself recursively.
#include <iostream>
#include <vector>
using namespace std;
namespace std
{
template<>
void vector<int>::push_back(const int &a)
{
cout << "in push_back: " << a << endl;
vector::push_back(a); // Want to call generic version
}
}
int main()
{
vector<int> v;
v.push_back(10);
v.push_back(1);
return 0;
}
When you create specialization for some template (no difference class of function), you tell to compiler to generate that one instead of general. So in fact if you have specialization you have no general version for that specialization and you can't call it, because it doesn't exists.
You can simply extract the code into another template function:
template<typename T>
void baseF(T t) { ... }
template<typename T>
void F(T t) { baseF<T>(t); }
template<>
void F<int>(int t) { baseF<int>(t); }
Well, to complement, I think it works for template function specification in some situations.
#include <iostream>
#include <vector>
using namespace std;
class Base
{
public:
virtual int test() {return 0;}
};
class Derived : public Base
{
public:
virtual int test() {return 1;}
};
template<class T>
void TestOutput(T* a)
{
cout << a->test() << endl;
}
template<>
void TestOutput(Derived* a)
{
cout << "something else" << endl;
TestOutput<Base>(a);
}
int main()
{
Derived d;
TestOutput(&d);
}
I compiled it with visual studio 2013 and the output is:
something else
1
Although I don't think you can always find a TestOutput function of Base to call the generic one.