我的基本想法是从std :: tuple派生我自己的类,以获得一些内部帮助器类型:
template <typename ... T>
class TypeContainer: public std::tuple<T...>
{
public:
using BaseType = std::tuple<T...>;
static const size_t Size = sizeof...(T);
TypeContainer(T... args):std::tuple<T...>(args...){};
using index_sequence = std::index_sequence_for<T...>;
};
Run Code Online (Sandbox Code Playgroud)
现在我尝试使用如下代码:
using MyType_tuple_with_empty = std::tuple< std::tuple<float,int>, std::tuple<>, std::tuple<int>>;
using MyType_typecontainer_with_empty = TypeContainer< TypeContainer<float,int>, TypeContainer<>, TypeContainer<int>>;
using MyType_tuple_non_empty = std::tuple< std::tuple<float,int>, std::tuple<int>, std::tuple<int>>;
using MyType_typecontainer_non_empty = TypeContainer< TypeContainer<float,int>, TypeContainer<int>, TypeContainer<int>>;
template <typename T>
void Do( const T& parms )
{
// The following lines result in errors if TypeContainer with
// …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种方法来比较两个元组,看它们是否包含相同的类型.
类型的顺序无关紧要.只要两个元组的类型之间存在一对一的映射,我就会认为它们是等价的.
这是我设置的一个小测试.
我无法实施equivalent_types():
#include <iostream>
#include <utility>
#include <tuple>
#include <functional>
template <typename T, typename U>
bool equivalent_types(T t, U u){
return (std::tuple_size<T>::value == std::tuple_size<U>::value);
//&& same types regardless of order
}
int main() {
//these tuples have the same size and hold the same types.
//regardless of the type order, I consider them equivalent.
std::tuple<int,float,char,std::string> a;
std::tuple<std::string,char,int,float> b;
std::cout << equivalent_types(a,b) << '\n'; //should be true
std::cout << equivalent_types(b,a) << '\n'; //should be true
//examples that …Run Code Online (Sandbox Code Playgroud) 我需要别名std::get功能,以提高我的代码的可读性.
不幸的是我遇到了编译时错误get<0> in namespace ‘std’ does not name a type.using相当于typedef它需要使用类型.我用a std::tuple来表示一些数据类型:
using myFoo = std::tuple<int,int,double,string>;
using getNumber = std::get<0>;
Run Code Online (Sandbox Code Playgroud)
我看一些以前的问题,但提出的解决方案是包装和使用std::forward.我不想为每个成员编写这样的代码.
有没有办法只使用关键字解决这个问题?
卡在TR1中,对于测试程序,我需要对特定类型的多个对象执行某些操作.我有几个元组类型定义,如下所示:
typedef std::tr1::tuple< bool
, signed char
, signed short
, signed int
, signed long long
, unsigned char
, unsigned short
, unsigned int
, unsigned long long > integral_types;
Run Code Online (Sandbox Code Playgroud)
从每个元组类型创建一个对象.然后我有类似这样的功能模板:
template<typename T>
void invoke_operation_1(T& obj);
Run Code Online (Sandbox Code Playgroud)
需要为元组对象中的所有对象调用它们.
我如何在C++ 03中做到这一点?
我需要为任意元组中的每个元素调用 - template或overloaded函数.确切地说,我需要在元组中指定元素,因为它们在元组中指定.
例如.我有一个元组std::tuple<int, float> t{1, 2.0f};和一个功能
class Lambda{
public:
template<class T>
void operator()(T arg){ std::cout << arg << "; "; }
};
Run Code Online (Sandbox Code Playgroud)
我需要一些结构/函数Apply,如果调用它Apply<Lambda, int, float>()(Lambda(), t)会产生:
1; 2.0f;
Run Code Online (Sandbox Code Playgroud)
而不是2.0f; 1;.
请注意,我知道解决方案,如果将"原始"参数包传递给函数,并且我知道如何以相反的顺序对元组执行此操作.但是以下部分特化的尝试Apply失败了:
template<class Func, size_t index, class ...Components>
class ForwardsApplicator{
public:
void operator()(Func func, const std::tuple<Components...>& t){
func(std::get<index>(t));
ForwardsApplicator<Func, index + 1, Components...>()(func, t);
}
};
template<class Func, class... Components>
class ForwardsApplicator < Func, sizeof...(Components), Components... > {
public:
void …Run Code Online (Sandbox Code Playgroud) 以下程序:
#include <iostream>
#include <tuple>
struct A {
A() { std::cout << "A constructor\n"; }
};
struct B {
B() { std::cout << "B constructor\n"; }
};
int main() {
std::tuple<A, B> t;
}
Run Code Online (Sandbox Code Playgroud)
在不同的编译器上提供不同的输出:
# libstdc++
B constructor
A constructor
# libc++
A constructor
B constructor
Run Code Online (Sandbox Code Playgroud)
这看起来很奇怪......我认为标准会保证元组元素按顺序构造,例如A,B,...,Y,Z?
在阅读这篇关于c ++ 17最终特性的摘要时,我对结构化绑定(强调我的)部分感到有些惊讶:
结构化绑定
到目前为止,有一种已知的技巧滥用std :: tie直接将元组或对分配给不同的变量,而不必手动处理结果类型.这是一个hack,并且变量必须存在,现在你可以声明变量并在一行中初始化它们:
auto [a,b,c] = getvalues();
需要大括号,getvalues返回一个元组.提案中没有提到std :: pair,因此不清楚它是否适用于在某些插入方法中由STL返回的pair.
我假设他们提到了这种用法 std::tie
int a,b,c;
std::tie(a,b,c) = std::make_tuple(1,2,3);
Run Code Online (Sandbox Code Playgroud)
我认为这是一种推荐的做法.
有人可以解释为什么他们将上述例子称为黑客攻击吗?
std::tuple<...>::operator!=如果两个比较元组中至少有一个成员不同,则返回true .
如果两个比较元组的所有成员不同,我需要一个返回true的函数:
template <class... Args>
bool areAllMembersDifferent( const std::tuple<Args...>& left, const std::tuple<Args...>& right )
{
bool allDiff = true;
// iterate through the tuples are set allDiff to false if one member's is different than other's
return allDiff;
}
Run Code Online (Sandbox Code Playgroud)
受到我在网络上发现的启发,我写了这个(改编了一个打印元组内容的函数):
template <std::size_t N, std::size_t, class = make_index_sequence<N>>
struct CheckTupleLoop;
template <std::size_t N, std::size_t J, std::size_t... Is>
struct CheckTupleLoop<N, J, index_sequence<Is...>> {
template <class Tup>
int operator()(bool& allDiff, const Tup &left,const Tup &right) {
if …Run Code Online (Sandbox Code Playgroud) 以下代码:
#include <tuple>
int main ()
{
auto f = [] () -> decltype (auto)
{
return std::get<0> (std::make_tuple (0));
};
return f ();
}
Run Code Online (Sandbox Code Playgroud)
(静默地)生成具有未定义行为的代码 - 返回的临时rvalue make_tuple通过std :: get <>和decltype(auto)传播到返回类型.因此它最终返回对超出范围的临时引用.请在此处查看https://godbolt.org/g/X1UhSw.
现在,你可以说我的使用decltype(auto)是错误的.但是在我的通用代码中(元组的类型可能是std::tuple<Foo &>),我不想总是复制.我真的想从元组中提取确切的值或引用.
我的感觉是这种超载std::get是危险的:
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >&&
get( tuple<Types...>&& t ) noexcept;
Run Code Online (Sandbox Code Playgroud)
虽然将左值引用传播到元组元素可能是明智的,但我认为这不适用于右值引用.
我确信标准委员会非常仔细地考虑了这一点,但任何人都可以向我解释为什么这被认为是最佳选择?
我正在尝试练习一些模板编程.也许有一种标准的方法可以做到这一点,我会感谢这些答案,但我的主要目标是练习模板编程技术,所以我试着自己实现它:
我需要连接多个元组,但作为类型,不像std::cat_tuple它.所以,我需要这样的东西cat<std::tuple<int, float>, std::tuple<char, bool>, ...>来获得std::tuple<int, float, char, bool, ...>的类型.
我当前的尝试失败并出现is not a template错误:
/* Concat tuples as types: */
template <typename first_t, typename... rest_t> struct cat {
using type = typename _cat<first_t, typename cat<rest_t...>::type>::type;
^^^^ cat is not a template
};
template <typename first_t, typename second_t>
struct cat<first_t, second_t> {
using type = typename _cat<first_t, second_t>::type;
^^^^ cat is not a template
};
// Concat two tuples:
template <typename, typename> struct …Run Code Online (Sandbox Code Playgroud) c++ template-meta-programming variadic-templates c++11 stdtuple
c++ ×10
stdtuple ×10
c++11 ×5
tuples ×4
c++14 ×2
c++17 ×2
c++03 ×1
comparison ×1
constructor ×1
libstdc++ ×1