问题描述
我有一个类
class C
{
public:
C ){}
private:
int timesTriggered_;
std :: map< std :: string,std :: tuple< std :: string,int,int,int,int,int> mapST;
std :: vector< std :: string> sv;
};
和此类型的某些对象:
C c1;
C c2;
C c3;
我有一个由C类字符串索引的地图
std :: map< std :: string,std :: list< C> cMap;
我将一些C类对象添加到地图中
cMap [1]。Push_back(c1);
cMap [2]。push_back(c2);
cMap [3]。push_back(c3);
我需要一个函数,当传递的std :: list将返回(例如有三个元素)
std :: tuple< C&& C&>(c1,c2,c3)
即使这需要返回一个std :: tuple,元组的项目总是相同类型, C.这必须工作,无论列表中有多少项目,虽然在编译时C对象的数量的上限是罚款。因此,本质上,这将一个列表(具有元素数量的上限)转换为可变元组。
这是一个函数,它返回我需要的:
< typename ... Obs> std :: tuple< Obs& ...> BindObservers(Obs& ... obs)
{
return std :: tuple< Obs& ...>(obs ...)
}
这样调用:
auto obs2 = BindObservers(c1,c2,c3);
问题是使用BindObservers我需要知道传递给它的参数数量,事物之间的逗号。我希望有一个BindObservers工作像这样:
auto obs2 = BindObservers(std :: list< C&
obs2看起来像(伪代码):
std :: tuple< C,C,这里的std :: list< C>的长度(std :: list< ; C>用逗号分隔)
所以这是一种模板元编程。 >
我需要它来使用c ++ 11,因为我没有c ++ 14编译器。
此代码在clang和g ++(使用C ++ 11)上正确运行:
生成 std :: tuple
和 Max_N
相同类型的元素,并用第一个值填充的给定列表。如果列表中的元素少于 Max_N
,则使用sentinel值填充最后一个元素。
c $ c> std :: array< C,N> 可能对于类似这样的东西更有用,如果需要从具有动态数量的元素的列表传递到来自常量
#include< tuple>
#include< type_traits>
#include< list>
#include< iostream>
#include< typeinfo>
template< std :: size_t Max_N,typename List>
class list_to_tuple {
public:
using value_type = typename List :: value_type;
using iterator_type = typename List :: const_iterator;
using tuple_type = decltype(std :: tuple_cat(
std :: tuple< typename List :: value_type>(),
typename list_to_tuple< Max_N-1,List&
));
tuple_type operator()(const List& lst,const value_type& sentinel){
return convert(lst.begin(),lst.end(),sentinel);
}
tuple_type convert(iterator_type begin,iterator_type end,const value_type& sentinel)const {
list_to_tuple< Max_N-剩余
if(begin!= end){
auto current = std :: make_tuple(* begin);
++ begin;
return std :: tuple_cat(current,remaining.convert(begin,end,sentinel));
} else {
return std :: tuple_cat(std :: make_tuple(sentinel),remaining.convert(begin,end,sentinel));
}
}
};
template< typename List>
class list_to_tuple< 0,List> {
public:
using value_type = typename List :: value_type;
using iterator_type = typename List :: const_iterator;
using tuple_type = std :: tuple<> ;;
tuple_type convert(iterator_type begin,iterator_type end,const value_type& sentinel)const {
return std :: tuple<>();
}
};
int main(){
std :: list< int> lst = {1,2,3};
list_to_tuple< 5,std :: list< int>> to_tup;
auto tup = to_tup(lst,0);
std :: cout<< std :: get< 0>(tup)<< std :: endl;
std :: cout<< std :: get< 1>(tup)<< std :: endl;
std :: cout<< std :: get< 2>(tup)<< std :: endl;
std :: cout<< std :: get< 3>(tup)<< std :: endl;
std :: cout<< std :: get< 4>(tup)< std :: endl;
std :: cout<< typeid(tup).name()< std :: endl;
}
I have a class
class C
{
public:
C() {}
private:
int timesTriggered_;
std::map<std::string, std::tuple<std::string, int, int, int, int, int>> mapST;
std::vector<std::string> sv;
};
and some objects of this type:
C c1;
C c2;
C c3;
I have a map indexed by strings of class C
std::map<std::string, std::list<C>> cMap;
I add some objects of class C into a map
cMap["1"].push_back(c1);
cMap["2"].push_back(c2);
cMap["3"].push_back(c3);
I need a function that when passed the std::list will return (for example with three elements) an
std::tuple<C&, C&, C&>(c1, c2, c3)
Even though this needs to return an std::tuple, the items of the tuple are always of the same type, C. This has to work no matter how many items in the list there are, although an upper bound of the number of C objects at compile time is fine. So in essence this turns a list (with an upper bound on the number of elements) into a variadic tuple.
Here is a function that returns what I need:
template <typename... Obs> std::tuple<Obs &...> BindObservers(Obs &... obs)
{
return std::tuple<Obs &...>(obs...);
}
And it is called like this:
auto obs2 = BindObservers(c1, c2, c3);
The problem is that to use BindObservers I need to know the number of parameters being passed to it, the things between the commas. I wish there was a BindObservers that worked like this:
auto obs2 = BindObservers(std::list<C>);
And obs2 would look like (pseudo-code):
std::tuple<C,C,more Cs here to the length of std::list<C>>(one parameter for each item in std::list<C> seperated by commas)
So it is a kind of template meta-programming.
I need it to work with c++11 since I don't have a c++14 compiler.
This code works correctly on clang and g++ (using C++11):
http://coliru.stacked-crooked.com/a/c8071ab447e10a31
Produces a std::tuple
with Max_N
elements of the same type, and fills it up with the first values of the given list. If less elements in list than Max_N
, fills the last elements with sentinel values.
In practice, using std::array<C, N>
may be more useful for something like this, if there is a need to pass from a list with a dynamic number of elements to one from a constant number of elements.
#include <tuple>
#include <type_traits>
#include <list>
#include <iostream>
#include <typeinfo>
template<std::size_t Max_N, typename List>
class list_to_tuple {
public:
using value_type = typename List::value_type;
using iterator_type = typename List::const_iterator;
using tuple_type = decltype(std::tuple_cat(
std::tuple<typename List::value_type>(),
typename list_to_tuple<Max_N-1, List>::tuple_type()
));
tuple_type operator()(const List& lst, const value_type& sentinel) {
return convert(lst.begin(), lst.end(), sentinel);
}
tuple_type convert(iterator_type begin, iterator_type end, const value_type& sentinel) const {
list_to_tuple<Max_N-1, List> remaining;
if(begin != end) {
auto current = std::make_tuple(*begin);
++begin;
return std::tuple_cat(current, remaining.convert(begin, end, sentinel));
} else {
return std::tuple_cat(std::make_tuple(sentinel), remaining.convert(begin, end, sentinel));
}
}
};
template<typename List>
class list_to_tuple<0, List> {
public:
using value_type = typename List::value_type;
using iterator_type = typename List::const_iterator;
using tuple_type = std::tuple<>;
tuple_type convert(iterator_type begin, iterator_type end, const value_type& sentinel) const {
return std::tuple<>();
}
};
int main() {
std::list<int> lst = {1, 2, 3};
list_to_tuple<5, std::list<int>> to_tup;
auto tup = to_tup(lst, 0);
std::cout << std::get<0>(tup) << std::endl;
std::cout << std::get<1>(tup) << std::endl;
std::cout << std::get<2>(tup) << std::endl;
std::cout << std::get<3>(tup) << std::endl;
std::cout << std::get<4>(tup) << std::endl;
std::cout << typeid(tup).name() << std::endl;
}
这篇关于转动BOUNDED std :: list< class>的参数转换为类型std :: tuple< class,class,class> tup< classObj1,classObj2,classObj2>的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!