How to use std::bind with std::function and std::map - c++11

I am trying to create a map of std::function and then trying to bind it few parameters, but it is giving an error.
So, my std::function definition is
using abc = std::function<double(const double& t1, const double& t2)>;
and the map is
std::map<std::pair<std::string, std::string>, abc> conversion_;
The way I am trying to insert in this map is
conversion_.emplace(
std::make_pair("a", "b"),
std::bind(conversion, 3, std::placeholders::_1));
conversion_.find(std::make_pair("a", "b"))->second(4); -- Access
I have defined the function conversion, but when I am trying to access the function it is giving the below error
error: no match for call to β€˜(const std::function<double(const double&, const double&)>) (int)’
Adding full code:
conversion function is defined in a separate file :
namespace x
{
double conversion(const double& a, const double& b);
}
Header file where I am trying to define map
namespace x
{
class main
{
public:
using abc = std::function<double(const double& t1, const double& t2)>;
main();
private:
std::map<std::pair<std::string, std::string>, abc> conversion_;
};
}
The CPP file
namespace x
{
main::main()
{
conversion_.emplace(
std::make_pair("a", "b"),
std::bind(conversion, 3, std::placeholders::_1));
auto m = conversion_.find(std::make_pair("a", "b"))->second(4);
}
}

I guess conversion is function as double(const double& t1, const double& t2). If so, std::bind(conversion, 3, std::placeholders::_1) define a functor which requires one argument a double (the other argument of conversion is fixed as 3) and return double. You just need modify abc into std::function<double(const double& t1)>;

Related

What is the correct way to call this method?

I'm trying to understand placeholders but i can't call this method. I have an implicit parameters Dummy{}, float and LastDummy{}. When i call function i skip these parameters. Also my call doesn't work.
struct AnotherDummy {};
struct YetAnotherDummy {};
struct LastDummy {};
class X { public:
void foo(std::string one, Dummy two, int three, AnotherDummy four,
float five, YetAnotherDummy six, double seven, int eight, LastDummy nine)
{
}
};
int main()
{
using namespace std::placeholders;
auto functor = std::bind(&X::foo, _6, _3, Dummy{}, _5, _1, 5.0f, _4, _2, _7, LastDummy{});
X obj;
functor(&obj, YetAnotherDummy{}, 1, 2.3f, 'x', AnotherDummy{}, Dummy{}, 2.3);
return 0;
}
For non-static member functions the object to call the function on (what becomes the this pointer inside the member function) is passed as a hidden first argument.
So the major problem with the usage of functor is that the X object obj should be the first argument to the function, i.e. placeholder _1. The remaining arguments starts at placeholder _2.
So you need to do e.g.
auto functor = std::bind(&X::foo, _1, _7, _4, Dummy{}, _6, _2, 5.0f, _5, _3, _8, LastDummy{});
Note that _1 is not the first argument to the function, and that the remaining placeholders have been increased by 1.

Using coeffRef with const CwiseUnaryView - Failing when multiplying two CWiseUnaryViews

I'm having some trouble when using coeffRef() with a CWiseUnaryView function, but only when the function is declared as const
Reproducible example:
#include <Eigen/Core>
struct dummy_Op {
EIGEN_EMPTY_STRUCT_CTOR(dummy_Op)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const double&
operator()(const double &v) const { return v; }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE double&
operator()(double &v) const { return v; }
};
void foo(Eigen::MatrixXd &out)
{
//Compiles
Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> view(out);
view.coeffRef(0,0);
//Doesn't Compile
const Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> const_view(out);
const_view.coeffRef(0,0);
}
Returns:
<source>: In function 'void foo(Eigen::MatrixXd&)':
<source>:21:28: error: passing 'const Eigen::CwiseUnaryView<dummy_Op,
Eigen::Matrix<double, -1, -1> >' as 'this' argument discards qualifiers
[-fpermissive]
const_view.coeffRef(0,0);
^
In file included from /opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/Core:413,
from <source>:1:
/opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/src/Core/DenseCoeffsBase.h:340:33: note:
in call to 'Eigen::DenseCoeffsBase<Derived, 1>::Scalar&
Eigen::DenseCoeffsBase<Derived, 1>::coeffRef(Eigen::Index, Eigen::Index)
[with Derived = Eigen::CwiseUnaryView<dummy_Op, Eigen::Matrix<double,
-1, -1> >; Eigen::DenseCoeffsBase<Derived, 1>::Scalar = double; Eigen::Index = long int]'
EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
^~~~~~~~
Compiler returned: 1
Compiler explorer: https://godbolt.org/z/kPHPuC
The side-effect of this, is that the multiplication of two (non-const) CWiseUnaryViews also fails, see example here: https://godbolt.org/z/JYQb3d
The bottom line is that you're calling a non-const method of a constant instance. The (first) coeffRef that is being called is the one (and only) in DenseCoeffsBase.h (DenseCoeffsBase<Derived, WriteAccessors>), which is not const qualified. The DenseCoeffsBase<Derived, ReadOnlyAccessors> class does not have a coeffRef method. You can get around this error (and get a warning) if you enable the -fpermissive compiler flag.
In the dense case, you probably want to use the operator()(Index, Index) method anyway, which does have a const qualified version. I just noticed the documentation explicitly says to use that method anyway, even for the non-const version. This is obviously not going to return a const reference, but at least in your example as a double, it shouldn't matter too much.
CwiseUnaryView is intended to be used for L-value like expression, e.g.,
MatrixXcd A;
A.real() = something; // `A.real()` is writable
If you want to apply an element-wise functor and use it as an R-value, you should use CwiseUnaryOp instead:
void foo(Eigen::MatrixXd &out)
{
Eigen::CwiseUnaryOp<dummy_Op, Eigen::MatrixXd> view1(out);
// shorter:
auto view2 = out.unaryExpr(dummy_Op());
Eigen::MatrixXd result = view1 * view2;
// or directly write: out.unaryExpr(dummy_Op()) * out.unaryExpr(dummy_Op());
}

C++11: Variadic template deduction logic

I have the following construct:
template <class... Args>
class some_class
{
public:
some_class() = default;
some_class(Args...) = delete;
~some_class() = default;
};
template<>
class some_class<void>
{
public:
some_class() = default;
~some_class() = default;
};
The reason for this is that I just want to allow the users to create objects using the default constructor, so for example:
some_class<int,float> b;
should work but
some_class<int,float> c(1,3.4);
should give me a compilation error.
At some point in time I also needed to create templates based on void hence, the specialization for void:
some_class<void> a;
But by mistake I have typed:
some_class<> d;
And suddenly my code stopped compiling and it gave me the error:
some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be
overloaded
some_class(Args...) = delete;
So here comes the question: I feel that I am wrong that I assume that some_class<> should be deduced to the void specialization... I just don't know why. Can please someone explain why some_class<> (ie: empty argument list) is different from some_class<void>? (A few lines from the standard will do :) )
https://ideone.com/o6u0D6
void is a type like any other (an incomplete type, to be precise). This means it can be used as a template argument for type template parameters normally. Taking your class template, these are all perfectly valid, and distinct, instantiations:
some_class<void>
some_class<void, void>
some_class<void, void, void>
some_class<void, char, void>
In the first case, the parameter pack Args has one element: void. In the second case, it has two elements: void and void. And so on.
This is quite different from the case some_class<>, in which case the parameter pack has zero elements. You can easily demonstrate this using sizeof...:
template <class... Pack>
struct Sizer
{
static constexpr size_t size = sizeof...(Pack);
};
int main()
{
std::cout << Sizer<>::size << ' ' << Sizer<void>::size << ' ' << Sizer<void, void>::size << std::endl;
}
This will output:
0 1 2
[Live example]
I can't really think of a relevant part of the standard to quote. Perhaps this (C++11 [temp.variadic] 14.5.3/1):
A template parameter pack is a template parameter that accepts zero or more template arguments. [ Example:
template<class ... Types> struct Tuple { };
Tuple<> t0; // Types contains no arguments
Tuple<int> t1; // Types contains one argument: int
Tuple<int, float> t2; // Types contains two arguments: int and float
Tuple<0> error; // error: 0 is not a type
β€”end example ]

C++11 Check two sets of variadic template arguments match

This question relates to an earlier one I asked regarding implementing something akin to Qt's signal/slots in C++11.
Consider the following (very simplified signal dispatcher, that in this example does nothing of any use, it's just to demonstrate the pattern/problem):
template< typename... TYPES >
class Signal
{
public:
Signal() = default;
~Signal() = default;
template< typename... PARAMETERS >
void broadcast( PARAMETERS &&... p )
{
// static_assert to confirm PARAMETERS can map to TYPES
}
};
This works well enough, but there's some unwanted type conversion going on in practice. e.g.;
// acceptable use.
Signal< int, unsigned, float, char >().broadcast( 1, 2u, 0.f, 'a' );
// should fail compilation, first parameter is a float, 4th is an int.
Signal< int, unsigned, float, char >().broadcast( 0.f, 0, 0.f, 0 );
// acceptable use, first parameter is const, but it's convertible.
const int i = 3;
Signal< int, unsigned, float, char >().broadcast( i, 2u, 0.f, 'a');
// acceptable use, first parameter is const &, but it's convertible.
const int & j = i;
Signal< int, unsigned, float, char >().broadcast( j, 2u, 0.f, 'a');
There should be no silent float to int conversion. Conversion of const/const & in this instance should be possible (the format of TYPES should not have const or & as all data should be passed by value).
I'd like to prevent compilation where such unwanted type conversion happens. I thought to wrap up both TYPES and PARAMETERS in tuples, iterate over the tuple and confirm that each type in a given tuple parameter index matches (including using std::decay), but then I couldn't see a way to do that at compile time so that it could go in a static_assert.
For reference, compilers of choice are clang (latest on OS X 7.3 (clang-703.0.31)) and vc14.
Is what I want to do possible and, if so, can anyone offer any pointers?
Using (once again) the all_true bool pack trick from Columbo:
template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
template <class... Args>
struct Signal {
template <class... Dargs, class = typename std::enable_if<all_true<
std::is_same<Args, typename std::decay<Dargs>::type>{}...
>{}>::type>
void broadcast(Dargs &&...) {}
};
This SFINAE's away the function if the parameters don't match exactly.
Here is a metaprogram I quickly came up with. It is a bit coarse, but can be implemented in a more better way. You should probably use the decayed type (std::decay) in the metaprogram to get correct result.
#include <iostream>
#include <type_traits>
template <typename... T> struct param_pack {};
template <typename, typename> struct is_all_same_impl;
template <>
struct is_all_same_impl<param_pack<>, param_pack<>>
{
static bool const value = true;
};
template <typename T, typename S, typename... Rest, typename... SRest>
struct is_all_same_impl<param_pack<T, Rest...>, param_pack<S, SRest...>>
{
static bool const value = false;
};
template <typename T, typename... Rest, typename... SRest>
struct is_all_same_impl<param_pack<T, Rest...>, param_pack<T, SRest...>>
{
static bool const value = is_all_same_impl<param_pack<Rest...>, param_pack<SRest...>>::value;
};
template <typename, typename>
struct is_all_same;
template <typename... FSet, typename... SSet>
struct is_all_same<param_pack<FSet...>, param_pack<SSet...>>: is_all_same_impl<param_pack<FSet...>, param_pack<SSet...>> {};
int main() {
std::cout << is_all_same<param_pack<int, char, float>, param_pack<int, char, int>>::value << std::endl;
return 0;
}
UPDATE :: More simpler version
template <typename... T> struct param_pack {};
int main() {
std::cout << std::is_same<param_pack<int, float, int>, param_pack<int,float,int>>::value << std::endl;
return 0;
}
So you can do something like:
static_assert( is_same<param_pack<Args...>, param_pack<std::decay_t<Dargs>...>>::value, "Parameters do not sufficiently match." );

Creating a new tuple class by popping the last type

I tried the following code but it gives:
main.cpp:29:22: error: aggregate 'pop<std::tuple<int, char, float> > p' has incomplete type and cannot be defined
What am I missing?
template <typename T>
struct pop;
template <typename E, typename... Ts>
struct pop<tuple<Ts..., E>> {
using result = tuple<Ts...>;
};
tuple<int, char, float> t;
typename pop<decltype(t)>::result p;
If Ts... must be at the end in a type list, why does it work in this example from http://en.cppreference.com/w/cpp/language/parameter_pack:
template<class A, class B, class...C> void func(A arg1, B arg2, C...arg3)
{
container<A,B,C...> t1; // expands to container<A,B,E1,E2,E3>
container<C...,A,B> t2; // expands to container<E1,E2,E3,A,B>
container<A,C...,B> t3; // expands to container<A,E1,E2,E3,B>
}
tuple<Ts..., E> is a non-deduced context. [temp.deduct.type]/9:
If P has a form that contains <T> or <i>, then each argument Pi of the respective template argument list P is compared with the corresponding argument Ai of the corresponding template argument list of A. If the template argument list of P contains a pack expansion that is not the last template argument, the entire template argument list is a non-deduced context.
That means that your partial specialization is never matched.
With C++14, one could use
template <class T, class=std::make_index_sequence<std::tuple_size<T>::value-1>>
struct pop;
template <typename Tuple, std::size_t... indices>
struct pop<Tuple, std::index_sequence<indices...>>
{
using type = std::tuple<std::tuple_element_t<indices, Tuple>...>;
};
template <typename T>
using pop_t = typename pop<T>::type;
Such that
using t = std::tuple<int, char, float>;
static_assert( std::is_same<pop_t<t>, std::tuple<int, char>>{}, "" );
Compiles.
Demo.
Ts... must be the last element of a type list if you want it to be deduced. tuple<Ts...,E> will not deduce Ts... to be all but the last, but rather never match anything.
Getting rid of the last argument is a bit tricker. live example:
#include <iostream>
#include <tuple>
#include <iostream>
namespace details {
template<class Lhs, class Rhs>
struct pop_helper;
template<template<class...>class Tup, class L0, class...Lhs, class...Rhs>
struct pop_helper<Tup<L0,Lhs...>, Tup<Rhs...>>:
pop_helper<Tup<Lhs...>, Tup<Rhs...,L0>>
{};
template<template<class...>class Tup, class L0, class...Rhs>
struct pop_helper<Tup<L0>, Tup<Rhs...>> {
using type=Tup<Rhs...>;
};
}
template <typename T>
struct pop;
template<template<class...>class Tup, class...Ts>
struct pop<Tup<Ts...>>:
details::pop_helper<Tup<Ts...>,Tup<>>
{};
template<typename T>
using pop_t=typename pop<T>::type;
std::tuple<int, char, float> t;
typedef pop_t<decltype(t)> p;
int main() {
p x = std::make_tuple( 7, 'x' );
std::cout << std::get<0>(x) << std::get<1>(x) << std::tuple_size<p>{} << "\n";
}
pop_helper moves the types over one at a time to the right hand side, until there is only one type left on the left hand side. Then it returns the right hand side type.
pop just passes the tuples over.
I used template<class...>class Tup instead of std::tuple, because why not support almost every template instead of just std::tuple?
pop_t gets rid of the annoying typename spam at point of use.
I use the inhertance-as-type-map-forwarding pattern, which saves on typing. With a type-map, the structure:
template<class X>
struct bob: foo<X> {};
can be read as bob<X> is foo<X>. The alternative is the more verbose
template<class X>
struct bob {
using type = typename foo<X>::type;
};
expanding variardic type lists is different than matching them. When it was designed, matching was kept simple in order to make compiler vendors be able to implement the feature. There may even be thorny issues beyond "it is tricky" down that path.
Another C++11 way to skin this cat:
#include <tuple>
template<class Tuple>
struct pop;
template<>
struct pop<std::tuple<>>
{
using type = std::tuple<>;
};
template<typename T1>
struct pop<std::tuple<T1>>
{
using type = std::tuple<>;
};
template<typename First, typename... Rest>
struct pop<std::tuple<First,Rest...>>
{
using type =
decltype(std::tuple_cat(
std::declval<std::tuple<First>>(),
std::declval<typename pop<std::tuple<Rest...>>::type>()));
};
// Test...
static_assert(std::is_same<pop<std::tuple<>>::type,std::tuple<>>::value,"");
static_assert(std::is_same<pop<std::tuple<int>>::type,std::tuple<>>::value,"");
static_assert(
std::is_same<pop<std::tuple<int,char>>::type,std::tuple<int>>::value,"");
static_assert(
std::is_same<pop<std::tuple<int,char,float>>::type,
std::tuple<int,char>>::value,"");
static_assert(
std::is_same<pop<std::tuple<int,char,float,double>>::type,
std::tuple<int,char,float>>::value,"");
This is the solution I had come up with:
template <typename T>
struct pop;
template <typename E, typename... Ts>
struct pop<std::tuple<E, Ts...>> {
using type = decltype(tuple_cat(
declval<tuple<E>>(),
declval<typename pop<tuple<Ts...>>::type>()
));
};
template <typename E>
struct pop<std::tuple<E>> {
using type = std::tuple<>;
};

Resources