c++ How to implement compose2 - c++

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <ctime>
#include <iterator>
#include <string>
#include <numeric>
template <typename BinaryFunction, typename UnaryFunction1, typename UnaryFunction2>
struct compose2 {
compose2(BinaryFunction binFunc, UnaryFunction1 unFunc1, UnaryFunction2 unFunc2)
: m_binFunc(binFunc)
, m_unFunc1(unFunc1)
, m_unFunc2(unFunc2)
{}
typedef typename BinaryFunction::return_type return_type;
typedef typename UnaryFunction1::argument_type argument_type;
return_type operator()(argument_type arg) {
return m_binFunc(m_unFunc1(arg), m_unFunc2(arg));
}
BinaryFunction m_binFunc;
UnaryFunction1 m_unFunc1;
UnaryFunction2 m_unFunc2;
};
int main() {
std::vector<int> v;
v.push_back(1);
v.push_back(75);
v.push_back(10);
v.push_back(65);
v.push_back(15);
v.push_back(78);
v.push_back(14);
v.push_back(19);
int x = 10, y = 20;
std::vector<int>::iterator it = std::find_if(v.begin(), v.end(),
compose2(
std::logical_and<bool>(),
std::bind1st(std::less<int>(), x),
std::bind1st(std::greater<int>(), y)
));
std::cout << (it - v.begin()) << std::endl;
}
I have tried to implement compose2 adaptor but this doesn't compile. I am getting main.cpp:43:29: error: missing template arguments before ‘(’ token and don’t know what template arguments I should pass. Why it doesn't detect the types.
I know that this is implemented in boost or other library or in new c++11 standard. But I only want to know why does my implementation fail. Thanks.

The compiler can only deduce template arguments for function templates, not class templates. That leaves you with a few choices: the most obvious (but often least convenient) is to specify the template parameters when you instantiate your compose2.
Marginally less obvious, but often more convenient is to create a function template that deduces the parameters, and creates a compose2 object using the deduced types:
template<class BinaryFunction, class UnaryFunction1, class UnaryFunction2>
compose2<BinaryFunction, UnaryFunction1, UnaryFunction2>
make_compose2(BinaryFunction binFunc, UnaryFunction1 unFunc1, UnaryFunction2 unFunc2) {
return compose2_t<BinaryFunction, UnaryFunction2, UnaryFunction2>
(binFunc, unFunc1, unFunc2);
}
Then the client code will use make_compose2 instead of compose2, and the template parameters can/will be deduced from the types of the passed parameters.

Related

Declare template function to accept any container but only one contained type

I want to declare a function that accepts different STL containers, but they must contain objects of a specific class (e.g. it should accept std::vector<double> and std::deque<double> but no std::vector<std::string>).
I have found answers for templating both the container and the contained types, but my attempts to adapt them so that the contained type is fixed have been unsuccessful.
You can do it with template template arguments (no typo). The first template argument of your template function is another template with a variadic number of template arguments. The second template argument are the variadic template arguments. In the signature you then fix the first template argument to the type you want (e.g. double) and let the compiler deduce the rest.
#include <deque>
#include <iostream>
#include <string>
#include <vector>
template < template < class ... > class Container, class ... Args >
void any_container(Container<double, Args...>)
{
// print what was deduced
std::cout << __PRETTY_FUNCTION__ << '\n';
}
int main()
{
std::vector<double> vd;
any_container(vd);
std::deque<double> dd;
any_container(dd);
std::vector<std::string> vs;
any_container(vs); // BOOM!
}
#PasserBy already hinted a different solution in this comment. Instead of having a substitution failure you could also just take the container as a template argument and the query its value_type in a static_assert. This has the advantage that you can put a custom error message.
#include <deque>
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
template <typename Container> void any_container(Container)
{
static_assert(std::is_same<typename Container::value_type, double>::value,
"BOOM!");
// print what was deduced
std::cout << __PRETTY_FUNCTION__ << '\n';
}
int main()
{
std::vector<double> vd;
any_container(vd);
std::deque<double> dd;
any_container(dd);
std::vector<std::string> vs;
any_container(vs); // BOOM!
}

STL container as template parameter in function, error in call

Cant understand what is wrogn with code, second function definition or call of this function in main?
I think, but not sure, problem in call, cause without calling code compiles well. Compiler gcc
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<class T>
void show_element(T ob)
{
cout << ob << " ";
}
template<template<class> class S, class T>
void show_sequence(S<T> sequence)
{
for_each(sequence.begin(), sequence.end(), show_element<T>);
}
int main(int argc, char const *argv[])
{
std::vector<int> v(20, 0);
//here the problem
show_sequence<std::vector<int>, int>(v);
return 0;
}
std::vector isn't a template of one parameter, it takes an allocator type as well. You can use it as vector<T> simply because the second parameter has a default (std::allocator<T>).
As it's written, your template function cannot accept any standard container, since off the top of my head, none take just a single type parameter.
An approach that would work, and not require you to know how many template parameters a container requires, is to accept a container type (not template), and glean the value type from the container type.
template<class Seq>
void show_sequence(Seq const& sequence)
{
typedef typename Seq::value_type T;
for_each(sequence.begin(), sequence.end(), show_element<T>);
}
All standard containers have a value_type member, so this will work with any of them. Furthermore, it will work with any container that takes its cue from the standard library.
The problem is that std::vector is a template but std::vector<int> is a type.
When you are giving the second one to the function, you are giving one type and not a template.
So, you can rewrite your function as :
template<class S>
void show_sequence(S sequence)
Moreover, vector does not take only one template paramete but two (see StoryTeller answer)
It is similar to this question: https://stackoverflow.com/a/29493191/1889040
It is because vector is template of <type, allocator>
The code should be
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<class T>
void show_element(T ob)
{
cout << ob << " ";
}
template<template<class,class> class S, class T, class Allocator>
void show_sequence(S<T, Allocator> sequence)
{
for_each(sequence.begin(), sequence.end(), show_element<T>);
}
int main(int argc, char const *argv[])
{
std::vector<int> v(20, 0);
//here problem solved
show_sequence<vector, int, allocator<int> > (v);
show_sequence(v);
return 0;
}

Error passing std::vector as a template template parameter - works in GCC, fails in MSVC

The following code
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <deque>
#include <functional>
#define BEGIN_TO_END(container) container.begin(), container.end()
template <template<typename...> class OutputContainerType, class InContainer>
OutputContainerType<typename InContainer::value_type> convertContainer(const InContainer& in)
{
OutputContainerType<typename InContainer::value_type> result;
std::transform(BEGIN_TO_END(in), std::back_inserter(result), [](typename InContainer::value_type value) {return value;});
return result;
}
int main() {
std::deque<int> d {1, 2, 3};
const auto v = convertContainer<std::vector>(d);
std::cout << v.size() << std::endl;
}
works fine with GCC (link). However, it doesn't compile with MSVC 2013 (12.0) with the error: 'std::vector' : class has no constructors (can be tested here, select 12.0 compiler version). What's the problem here, and how can I fix it?
The code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <deque>
#include <functional>
#define BEGIN_TO_END(container) container.begin(), container.end()
template <template<typename T, typename T2> class OutputContainerType, class InContainer>
OutputContainerType<typename InContainer::value_type, std::allocator<typename InContainer::value_type>> convertContainer(const InContainer& in)
{
OutputContainerType<typename InContainer::value_type, std::allocator<typename InContainer::value_type>> result;
std::transform(BEGIN_TO_END(in), std::back_inserter(result), [](typename InContainer::value_type value) {return value;});
return result;
}
int main() {
std::deque<int> d {1, 2, 3};
const auto v = convertContainer<std::vector>(d);
std::cout << v.size() << std::endl;
}
Worked. The problem is then with variadic number of template parameters here...
EDITED:
Actually not with the variadic number of template parameters as I can even compile it with the
template <template<typename...> class OutputContainerType, class InContainer>
so the MSVC compiler needs explicitly given each type of the template.

Construct a boost variant containing a value of the nth-type in the variant type index?

I want to construct boost::variants containing default-constructed values, specified with a type index - without writing my own switch statement over the type index.
I figure this must be possible, somehow, with MPL?
To clarify though, the index is not a compile-time constant expression.
The use case is that I need to construct a variant which will later be replaced with one containing the correct value, but at this point I only know the type index. Think of it as a lazy deserialisation problem.
You need to use the variant::types typedef. This gives you an MPL compatible sequence which we can then use with mpl::at and a template to do our bidding. This does the trick:
#include <string>
#include <boost/variant.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
template<typename U, typename V>
void construct_in(V& v) {
v = U();
// modern
// v = U{};
}
int main()
{
typedef boost::variant<int, std::string> variant;
typedef boost::mpl::at<variant::types, boost::mpl::int_<1>>::type pos;
variant v;
// use type deduction
construct_in<pos>(v);
// does not throw, does work
std::string& s =boost::get<std::string>(v);
return 0;
}
Here goes the runtime-variant:
#include <string>
#include <vector>
#include <functional>
#include <boost/variant.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/for_each.hpp>
typedef boost::variant<int, std::string> variant;
typedef variant::types types;
typedef std::vector< std::function<void(variant&)> > fvec;
template<typename U, typename V>
void construct_in(V& v) {
v = U{};
}
struct build_and_add {
fvec* funcs;
template<typename T>
void operator()(T) {
funcs->push_back(&construct_in<T, variant>);
}
};
int main()
{
variant v;
std::vector< std::function<void(variant&)> > funcs;
// cannot use a lambda, would need to be polymorphic
build_and_add f = {&funcs};
boost::mpl::for_each<types>(f);
// this is runtime!
int i = 1;
funcs[i](v);
// does not throw, does work
std::string& s =boost::get<std::string>(v);
return 0;
}
It's a little arcane and will need some tweaking with variadic
arguments to be truly generic, but it does what you want. Someone else needs to figure out if this results in significant
code blow-up.

What is the difference between function templates and class templates?

I am confused about the strange syntax provided by C++ function templates and class templates. Take a quick look at the code below:
#include <iostream>
#include <algorithm>
#include <functional>
#include <iterator>
#include <vector>
using namespace std;
template <class op1,class op2>
class compose_fg_x_t : public unary_function<typename op2::argument_type,typename op1::result_type>{
public:
// constructor
compose_fg_x_t(const op1& arg1,const op2& arg2): p1(arg1),p2(arg2){
}
//function call
typename op1::result_type operator()(const typename op2::argument_type& x) const{
return p1(p2(x));
}
private:
op1 p1;
op2 p2;
};
template <class Op1,class Op2>
inline compose_fg_x_t<Op1,Op2> compose_fg_x(const Op1& p1,const Op2& p2){
return compose_fg_x_t<Op1,Op2>(p1,p2);
}
int main(int argc, char *argv[])
{
int a[] = {1,2,3,4,5};
vector<int> IntVec(a,a+sizeof(a)/sizeof(int));
copy(IntVec.begin(),IntVec.end(),ostream_iterator<int>(cout," "));
cout<<endl;
transform(IntVec.begin(),IntVec.end(),ostream_iterator<int>(cout," "),compose_fg_x( bind2nd(multiplies<int>(),5),bind2nd(plus<int>(),10) ));
transform(IntVec.begin(),IntVec.end(),ostream_iterator<int>(cout," "),compose_fg_x_t( bind2nd(multiplies<int>(),5),bind2nd(plus<int>(),10) ));
return 0;
}
So, my question is, why is the first transform is correct while the second is not? What the helper function compose_fg_x does is return an object of the underlying compose_fg_x_t type. I am trying to omit the indirect function call, which fails to compile. Why?
Template arguments can only be deduced for function templates, not for class templates. The whole point of helper functions such as make_pair (or your compose_fg_x) is to circumvent this limitation.
Here is a slightly less complicated example that demonstrates the problem:
#include <utility>
int main()
{
auto x = std::make_pair(3, 4); // function template arguments are deduced
auto y = std::pair(3, 4); // error: missing class template arguments
}