I'm trying to implement a zip function. zip's parameters are each wrapped<Ti>, where Ti varies from parameter to parameter.
zip takes these wrapped<Ti>s and produces a wrapped<tuple<T1&,T2&,...TN&>>, or in other words a wrapped tuple of references to its parameters. The references should preserve const-ness.
Here's my first stab at zip with one parameter, which doesn't work in general:
#include <utility>
#include <tuple>
// implement forward_as_tuple as it is missing on my system
namespace ns
{
template<typename... Types>
std::tuple<Types&&...>
forward_as_tuple(Types&&... t)
{
return std::tuple<Types&&...>(std::forward<Types>(t)...);
}
}
template<typename T>
struct wrapped
{
wrapped(T &&x)
: m_x(std::forward<T>(x))
{}
T m_x;
};
template<typename T>
wrapped<std::tuple<T&&>>
zip(wrapped<T> &&x)
{
auto t = ns::forward_as_tuple(std::forward<T>(x.m_x));
return wrapped<std::tuple<T&&>>(t);
}
int main()
{
wrapped<int> w1(13);
wrapped<int> &ref_w1 = w1;
// OK
zip(ref_w1);
const wrapped<int> &cref_w1 = w1;
// XXX won't compile when passing a const reference
zip(cref_w1);
return 0;
}
Is there a way to implement the general, variadic case with a single version of zip?
Admittedly, I don't have a C++0x compiler that handles variadic templates, so I can't test it. But this might do the trick.
template<typename T>
struct wrapped
{
wrapped(T &&x)
: m_x(std::forward<T>(x))
{}
typedef T type;
T m_x;
};
template<typename... Types>
wrapped<std::tuple<Types&&...>> zip(wrapped<Types>&&... x)
{
return wrapped<std::tuple<Types&&...>>(std::tuple<Types&&...>(std::forward<Types>(x.m_x)...));
}
I'm not entirely sure if it is legal to call zip like this:
zip(wrapped<T1>(value1), wrapped<T2>(value2));
You may have to explicitly qualify the call:
zip<T1, T2>(wrapped<T1>(value1), wrapped<T2>(value2));
Here's the solution I arrived at:
#include <utility>
#include <tuple>
#include <cassert>
template<typename T>
struct wrapped
{
wrapped(T &&x)
: m_x(std::forward<T>(x))
{}
T m_x;
};
template<typename Tuple>
wrapped<Tuple> make_wrapped_tuple(Tuple &&x)
{
return wrapped<Tuple>(std::forward<Tuple>(x));
}
template<typename... WrappedTypes>
decltype(make_wrapped_tuple(std::forward_as_tuple(std::declval<WrappedTypes>().m_x...)))
zip(WrappedTypes&&... x)
{
return make_wrapped_tuple(std::forward_as_tuple(x.m_x...));
}
int main()
{
wrapped<int> w1(1);
wrapped<int> w2(2);
wrapped<int> w3(3);
wrapped<int> w4(4);
auto z1 = zip(w1,w2,w3,w4);
z1.m_x = std::make_tuple(11,22,33,44);
assert(w1.m_x == 11);
assert(w2.m_x == 22);
assert(w3.m_x == 33);
assert(w4.m_x == 44);
const wrapped<int> &cref_w1 = w1;
auto z2 = zip(cref_w1, w2, w3, w4);
// does not compile, as desired
// z2.m_x = std::make_tuple(111,222,333,444);
return 0;
}
Having zip take WrappedTypes... instead of wrapped<T>... isn't as satisfying a solution, but it works.
template<typename T>
struct wrapped
{
wrapped(T &&x)
: m_x(std::forward<T>(x))
{}
typedef T type;
T m_x;
};
template<typename... Types>
wrapped<std::tuple<T&&...>> zip(wrapped<Types>... &&x)
{
return G+
Related
I want to have a template function which accepts unary member-function pointers of an instance of some generic type.
My problem is that I must support both void(T val) and void(const T& val) member functions.
I have written one template function for each case and it works fine, but this leads to code duplication since the function logic is completely the same. (I found something completely similar here: Function taking both pointer to member-function and pointer to const member-function but I fail to see a definitive solution).
An example of the generic type mentioned above:
using UserAddress = std::string;
class User
{
private:
int mHeight;
UserAddress mAddress;
public:
void SetHeight(int height){mHeight = height;}
void SetAddress(const UserAddress& address){mAddress = address;}
};
Where UserAddress is some heavy type I want to pass by reference.
My templated function:
template <typename TPersistentObject>
class Persistence
{
private:
std::map<std::string, std::function<void(User*)>> mSetterOfProperty;
template <typename TPersistentObject, typename TPropertyValue>
void DefinePropertySettingMethod(const std::string& propertyName,
void (TPersistentObject::*propertySetter)(TPropertyValue), std::function<TPropertyValue(void)> dataReader)
{
mSetterOfProperty[propertyName] =
[propertySetter, columnDataReader](TPersistentObject* persistentObject)
{
(persistentObject->*propertySetter)(dataReader());
};
}
};
/// Const& implementation leading to code duplication
template <typename TPersistentObject, typename TPropertyValue>
void DefinePropertySettingMethod(const std::string& propertyName,
void (TPersistentObject::*propertySetter)(const TPropertyValue&), std::function<TPropertyValue(void)> dataReader)
{
...
}
};
Is there some way to define this function to support the following:
int main()
{
auto intDataReader = []() {
return 1;
};
auto stringDataReader = []() {
return UserAddress("Next Door");
};
Persistence p;
p.DefinePropertySettingMethod<User,int>("Height", &User::SetHeight, intDataReader);
p.DefinePropertySettingMethod<User,UserAddress>("Address", &User::SetAddress, stringDataReader);
}
Thanks to Igor Tandetnik 's tip I managed to compile a solution. std::enable_if is not what I needed though since I did not need to deactivate an overload (or at least I couldn't come to a solution using it).
std::conditional did the trick.
Here is the code:
#include <string>
#include <functional>
#include <map>
#include <string>
#include <type_traits>
using UserAddress = std::string;
class User
{
private:
int mHeight;
UserAddress mAddress;
public:
void SetHeight(int height){mHeight = height;}
void SetAddress(const UserAddress& address){mAddress = address;}
};
template <typename TPersistentObject>
class Persistence
{
public:
std::map<std::string, std::function<void(TPersistentObject*)>> mSetterOfProperty;
template <typename TPropertyValue>
void DefinePropertySettingMethod(const std::string& propertyName,
void (TPersistentObject::*propertySetter)(TPropertyValue),
std::function<
typename std::conditional<!std::is_same<TPropertyValue, typename std::decay<TPropertyValue>::type>::value,
typename std::decay<TPropertyValue>::type, TPropertyValue>::type
(void)> dataReader)
{
mSetterOfProperty[propertyName] =
[propertySetter, dataReader](TPersistentObject* persistentObject)
{
(persistentObject->*propertySetter)(dataReader());
};
}
};
int main()
{
std::function<int()> intDataReader = []() {
return 1;
};
std::function<std::string()> stringDataReader = []() {
return UserAddress("Next Door");
};
Persistence<User> p;
p.DefinePropertySettingMethod("Height", &User::SetHeight, intDataReader);
p.DefinePropertySettingMethod("Address", &User::SetAddress, stringDataReader);
}
I have a template class(CrMultiIndex) that receive as template parameter a definition of boost multi index(GlobalHash).
I need :
To add statistics to my template class according to Index used.
So i need a way to resize the vector(m_StatsByIndex) at init with the number of existing indices.
I still want the user to search according to tag and not index number.
So i need a way to convert from tag to index number so i can update statistics in vector according to index in vector.
I have template class
template <typename KeysType, typename MultiIndexType>
class CrMultiIndex
{
std::vector<SrStatisticsByIndex> m_StatsByIndex;
public:
MultiIndexType *m_pMultiIndex=NULL;
CrMultiIndex()
{
m_pMultiIndex = new MultiIndexType(typename
MultiIndexType::ctor_args_list());
}
Here is the definition of boost multi index container:
typedef boost::multi_index::multi_index_container<
CrUsersKeys,
UsersKey_hash_indices/*,
bip::allocator<CrUsersKeys,bip::managed_shared_memory::segment_manager>*/
> GlobalHash;
with a search function according to Tag
template <typename TagType,typename SearchingKey>
typename MultiIndexType::template index<TagType>::type::iterator
GetIteratorBy(SearchingKey & key)
{
return m_pMultiIndex->template get<TagType>().find(key) ;
}
Code is at http://coliru.stacked-crooked.com/a/d97195a6e4bb7ad4
You'd need to query the embedded index type lists:
typedef typename MultiIndexType::index_type_list::size NumberOfIndexes;
template <typename Tag> constexpr static size_t IndexOfTag() {
namespace mpl = boost::mpl;
using tl = typename MultiIndexType::index_type_list;
using B = typename mpl::begin<tl>::type;
using helper = typename MultiIndexType::template index<Tag>;
static_assert(helper::index_found, "index not found");
auto N = mpl::distance<B, typename helper::iter>::value;
return N;
}
Or, using Boost Mpl all the way:
typedef typename MultiIndexType::index_type_list::size NumberOfIndexes;
template <typename Tag> constexpr static size_t IndexOfTag() {
namespace mpl = boost::mpl;
using tl = typename MultiIndexType::index_type_list;
using B = typename mpl::begin<tl>::type;
using E = typename mpl::end<tl>::type;
using It = typename mpl::find_if<tl, bmi::detail::has_tag<Tag> >::type;
static_assert(not std::is_same<E, It>(), "index not found");
auto N = mpl::distance<B, It>::value;
return N;
}
You can use it like so:
template <typename TagType, typename SearchingKey>
typename MultiIndexType::template index<TagType>::type::iterator
GetIteratorBy(SearchingKey &key) {
auto& idx = m_pMultiIndex.template get<TagType>();
auto& stats = GetStats<TagType>();
auto it = idx.find(key);
++(it == idx.end()? stats.searchedNotFound : stats.searchedSuccessfully);
return it;
}
DEMO
Note the code has been simplified:
Live On Coliru
#include <iostream>
#include <boost/multi_index/member.hpp> // for member
#include <boost/multi_index/hashed_index.hpp> // for hashed_unique
#include <boost/multi_index/ordered_index.hpp> // for ordered_non_unique
#include <boost/multi_index_container.hpp> // for multi_index_container
namespace bmi = boost::multi_index;
struct SrStatisticsByIndex {
int deleted;
int searchedSuccessfully;
int searchedNotFound;
};
template <typename MultiIndexType, typename ValueType = typename MultiIndexType::value_type>
class CrMultiIndex {
typedef typename MultiIndexType::index_type_list::size NumberOfIndexes;
template <typename Tag> constexpr static size_t IndexOfTag() {
using tl = typename MultiIndexType::index_type_list;
using B = typename boost::mpl::begin<tl>::type;
using helper = typename MultiIndexType::template index<Tag>;
static_assert(helper::index_found, "index not found");
return boost::mpl::distance<B, typename helper::iter>::value;
}
public:
MultiIndexType m_pMultiIndex;
template <typename Tag> SrStatisticsByIndex& GetStats()
{ return m_StatsByIndex.at(IndexOfTag<Tag>()); }
template <typename Tag> SrStatisticsByIndex const& GetStats() const
{ return m_StatsByIndex.at(IndexOfTag<Tag>()); }
// All the protected function are non locking function
template <typename TagType, typename SearchingKey>
typename MultiIndexType::template index<TagType>::type::iterator
GetIteratorBy(SearchingKey &key) {
auto& idx = m_pMultiIndex.template get<TagType>();
auto& stats = GetStats<TagType>();
auto it = idx.find(key);
++(it == idx.end()? stats.searchedNotFound : stats.searchedSuccessfully);
return it;
}
void Insert(ValueType const &key) {
std::cout << (m_pMultiIndex.insert(key).second? "success":"failed") << std::endl;
}
private:
std::vector<SrStatisticsByIndex> m_StatsByIndex { NumberOfIndexes() };
};
class CrUsersValue {
int val1;
int val2;
};
class CrUsersKeys {
public:
int IMSI;
int TIMESTAMP;
CrUsersValue val;
};
typedef boost::multi_index::multi_index_container<
CrUsersKeys,
bmi::indexed_by<
bmi::ordered_non_unique<bmi::tag<struct TIMESTAMP_tag>,
bmi::member<CrUsersKeys, int, &CrUsersKeys::TIMESTAMP> >,
bmi::hashed_unique<bmi::tag<struct IMSI_tag>,
bmi::member<CrUsersKeys, int, &CrUsersKeys::IMSI> /*, boost::hash<int>, std::equal_to<int>*/>
>
/*, bip::allocator<CrUsersKeys,bip::managed_shared_memory::segment_manager>*/
>
GlobalHash;
int main() {
CrMultiIndex<GlobalHash> multi;
CrUsersKeys key;
key.IMSI = 2;
multi.Insert(key);
int searchKey = 2;
auto it = multi.GetIteratorBy<IMSI_tag>(searchKey);
if (it != multi.m_pMultiIndex.get<IMSI_tag>().end())
std::cout << "found " << std::endl;
}
Prints
success
found
As a supplement to sehe's answer, this a rewrite of IndexOfTag that does not depend on undocumented Boost.MultiIndex features:
Live On Coliru
template<typename MultiIndexContainer,std::size_t N=0>
struct index_position:index_position<MultiIndexContainer,N+1>
{
using index_type=typename boost::multi_index::nth_index<MultiIndexContainer,N>::type;
using index_position<MultiIndexContainer,N+1>::case_of;
static constexpr std::size_t case_of(std::in_place_type_t<index_type>){return N;}
};
template<typename MultiIndexContainer>
struct index_position<
MultiIndexContainer,
boost::mpl::size<typename MultiIndexContainer::index_type_list>::value
>
{
static constexpr void case_of(...){}
};
template <typename MultiIndexContainer,typename Tag>
constexpr std::size_t IndexOfTag()
{
using index_type=typename boost::multi_index::index<MultiIndexContainer,Tag>::type;
return index_position<MultiIndexContainer>::case_of(std::in_place_type<index_type>);
}
Edit: In C++14:
Live On Coliru
template<typename MultiIndexContainer,std::size_t N=0>
struct index_position:index_position<MultiIndexContainer,N+1>
{
using index_type=typename boost::multi_index::nth_index<MultiIndexContainer,N>::type;
using index_position<MultiIndexContainer,N+1>::case_of;
static constexpr std::size_t case_of(index_type*){return N;}
};
template<typename MultiIndexContainer>
struct index_position<
MultiIndexContainer,
boost::mpl::size<typename MultiIndexContainer::index_type_list>::value
>
{
static constexpr void case_of(...){}
};
template <typename MultiIndexContainer,typename Tag>
constexpr std::size_t IndexOfTag()
{
using index_type=typename boost::multi_index::index<MultiIndexContainer,Tag>::type;
return index_position<MultiIndexContainer>::case_of((index_type*)(nullptr));
}
I know one could check the existence of a particular method using expression SFINAE in C++11 as follows.
What I can't find though, is an example to do the same, checking method arguments as well. In particular I would like to match a method that takes a const parameter.
#include <iostream>
struct A
{
void method() const
{
return;
}
};
template <typename T, typename = std::string>
struct hasMethod
: std::false_type
{
};
template <typename T>
struct hasMethod<T, decltype(std::declval<T>().method())>
: std::true_type
{ };
int main() {
std::cout << hasMethod<A>::value << std::endl;
}
In reality I would like the hasMethod:: to match
void method(const Type& t) const
{
return;
}
What is the syntax to pass to decltype?
I have tried:
struct hasMethod<T, decltype(std::declval<T>().method(const int&))>
: std::true_type
but it obviously doesn't work.
I am trying to wrap my head around parameter packs and need a little help.
Looking at the contrived example below, Is there a way to compare Args to T and only allow bar() to compile if they match? For example if I create Task<void(int, char, float)> I want bar(float, char, float) not to compile but bar(int, char, float) to compile just fine. Is this even feasible?
template <typename... Types>
struct foo {};
template<typename T>
struct Task;
template<typename R, typename...Args>
struct Task<R(Args...)>
{
template<typename... T>
std::enable_if<is_same<T, Args>
void bar(T... args)
{
//do something here
}
};
int main()
{
Task<int(int)> task;
int a = 0;
float b = 1.0;
bool c = false;
//compiles
task.bar(a);
//none of these should compile
task.bar(b);
task.bar(c);
task.bar(a, b);
task.bar(a, b, c);
}
First, syntax should be:
template<typename R, typename...Args>
struct Task<R(Args...)>
{
template<typename... T>
std::enable_if<is_same<tuple<T...>, tuple<Args...> >::value > bar(T... args)
{
//do something here
}
};
Which compiles fine, because of SFINAE: while trying to instantiate bar(bool) for example, first instantiation fails with bool type, but an instantiation exists when performing conversion of parameter to int.
To get desired effect, you need the hard type check to happen after instantiating the template:
#include <type_traits>
#include <tuple>
template<typename T>
struct Task;
template<typename R, typename... Args>
struct Task<R(Args...)>
{
template<typename... OtherArgs>
void bar(OtherArgs... otherArgs)
{
static_assert(
std::is_same<std::tuple<Args...>, std::tuple<OtherArgs...> >::value,
"Use same args types !"
);
// Do something
}
};
int main()
{
Task<int(int)> task;
// Compiles fine
task.bar(1);
// Fails to compile
task.bar('u');
task.bar(0ul);
return 0;
}
I have the following code:
#include <iostream>
#include <functional>
class test
{
public:
typedef std::function<bool(int)> Handler;
void handler(Handler h){h(5);}
};
class test2
{
public:
template< typename Ret2, typename Ret, typename Class, typename Param>
inline Ret2 MemFn(Ret (Class::*f)(Param), int arg_num)
{
if (arg_num == 1)
return std::bind(f, this, std::placeholders::_1);
}
bool f(int x){ std::cout << x << std::endl; return true;}
};
int main()
{
test t;
test2 t2;
t.handler(t2.MemFn<test::Handler>(&test2::f, 1));
return 0;
}
It works as expected.
I would like to be able to call this:
t.handler(t2.MemFn<test::Handler>(&test2::f));
instead of
t.handler(t2.MemFn<test::Handler>(&test2::f, 1));
Basically I need MemFn to determine in runtime what Handler expects as the number of arguments.
Is that even possible?
You may create some type_traits to have your info, something like:
template <typename T> struct function_trait;
template <typename Ret, typename ... Args>
struct function_trait<std::function<Ret(Args...)>>
{
static constexpr std::size_t args_count = sizeof...(Args);
};
And so your method may look like:
template<typename Ret2, typename Ret, typename Class, typename Param>
inline Ret2 MemFn(Ret (Class::*f)(Param))
{
if (function_trait<Ret2>::args_count == 1)
return std::bind(f, this, std::placeholders::_1);
throw std::runtime_error("invalid number of arguments");
}