gcc 4.7.1对元组进行空基类优化,我认为这是一个非常有用的功能.但是,似乎有一个意外的限制:
#include <tuple>
#include <cstdint>
#include <type_traits>
class A { };
class B : public A { std::uint32_t v_; };
class C : public A { };
static_assert(sizeof(B) == 4, "A has 32 bits.");
static_assert(std::is_empty<C>::value, "B is empty.");
static_assert(sizeof(std::tuple<B, C>) == 4, "C should be 32 bits.");
Run Code Online (Sandbox Code Playgroud)
在这种情况下,最后一个断言失败,因为元组实际上大于4个字节.有没有办法避免这种情况,而不打破类层次结构?或者我是否必须实现我自己的对实现,以其他方式优化这种情况?
这是一个非常好的(不是我的)示例,你可以如何扩展(或"爆炸")元组作为函数的参数:
template<int ...I> struct index_tuple_type {
template<int N> using append = index_tuple_type<I..., N>;
};
template<int N> struct make_index_impl {
using type = typename make_index_impl<N-1>::type::template append<N-1>;
};
template<> struct make_index_impl<0> { using type = index_tuple_type<>; };
template<int N> using index_tuple = typename make_index_impl<N>::type;
template <typename I, typename ...Args>
struct func_traits;
template <typename R, int ...I, typename ...Args>
struct func_traits<R, index_tuple_type<I...>, Args...> {
template <typename TT, typename FT>
static inline R call(TT &&t, FT &&f) {
return f(std::get<I>(std::forward<TT>(t))...);
}
};
template<
typename …Run Code Online (Sandbox Code Playgroud) 我想写一个比较器,它比较不同长度但具有相同"前缀"的元组.考虑以下情况,我有两个元组.
auto t1 = std::make_tuple(10, "Test1");
auto t2 = std::make_tuple(10, "Test", 3.14);
Run Code Online (Sandbox Code Playgroud)
我想对t1 <t2应用"less",其中只比较两个元组的第一个成员(相同的类型?)而第三个只是省略.可能吗?
下面的代码为 a 实现了一个散列函数,std::tuple然后在我的代码库的不同段中使用 a std::unordered_mapof std::tuples。
// compute hash function recursively through each std::tuple element
template<class Tuple, std::size_t N>
struct tuple_hash_compute {
static std::size_t hash_compute(const Tuple& t) {
using type = typename std::tuple_element<N-1, decltype(t)>::type; // OFFENDING LINE
return tuple_hash_compute<Tuple, N-1>::hash_compute(t)
+ std::hash<type>()(std::get<N-1>(t));
}
};
// base helper
template<class Tuple>
struct tuple_hash_compute<Tuple, 1> {
static std::size_t hash_compute(const Tuple& t) {
using type = typename std::tuple_element<0, decltype(t)>::type; // OFFENDING LINE
return 51U + std::hash<type>()(std::get<0>(t))*51U;
}
};
// tuple_hash …Run Code Online (Sandbox Code Playgroud) 我只是读一些关于元组的内容.
现在我不清楚以下语法:
std::tie (myint, std::ignore, mychar) = mytuple;
Run Code Online (Sandbox Code Playgroud)
掌握它的作用并不难,但从语言的角度来看会发生什么?我们以某种方式分配函数的返回值?
考虑:
std::tuple<bool, double, int> getTuple()
{
return {};
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,标准对结果元组中的值有何看法?是否保证例如 bool 总是假的?
的函数签名std::apply不会将模板参数限制Tuple为 的特化std::tuple,因此它仍然可以接受定义(godbolt)的类似元组的对象:std::tuple_size_v
#include <tuple>
#include <utility>
#include <array>
int main() {
std::apply([](int, int) {}, std::array{0, 0});
std::apply([](int, int) {}, std::pair {0, 0});
std::apply([](int, int) {}, std::tuple{0, 0});
}
Run Code Online (Sandbox Code Playgroud)
但[tuple.apply]std::apply中的描述是:
tuple20.5.5 使用参数调用函数
这是否意味着应用于std::apply除此之外的对象std::tuple是未定义的行为?
我有一个像这样的参数包
<int, long, string, double>
Run Code Online (Sandbox Code Playgroud)
和一个像这样的字符串
"100 1000 hello 1.0001"
Run Code Online (Sandbox Code Playgroud)
如何解析这些数据并将它们打包到 std::tuple<int, long, string, double>
我想要一个有数组元素作为成员的元组.特别是,我希望这个数组元素是2D - 所以任何答案都必须超过1D.我理想的是我可以用初始化列表初始化的东西,例如std::tuple<ARRAY_TYPE, ...>({{0, 1}, {2, 3}}, ...).
看起来这样的元组很难构造,需要手动初始化(即,用于循环等).这是我尝试过的:
std::tuple<int[M][N], ...> - 由于C风格数组的限制,这不起作用.元组本身是一个有效的类型,但初始化需要手动完成(不是在构建时).
std::tuple<std::array<std::array<int, M>, N>, ...>- 我认为这会起作用,但由于某种原因,像std::tuple<std::array<std::array<int, 2>, 2>, ...>({{0, 1}, {2, 3}}, ...)"没有匹配的构造函数错误"的失败.它确实在1D工作.
std::tuple<std::vector<std::vector<int>>, ...>({{0, 1}, {2, 3}}, ...)实际上确实有效,但是这里的矢量似乎有些过分
有什么想法吗?有什么方法可以让C风格的数组工作吗?那将是理想的.
我有一个功能(简化逻辑后)采取的形式
std::tuple<font_heap, font_heap> get_font_heaps(std::vector<uint8_t> const& a, std::vector<uint8_t> const& b) {
return std::make_tuple(get_font_heap_from_data(a), get_font_heap_from_data(b));
}
Run Code Online (Sandbox Code Playgroud)
我想对这个函数进行模板化处理,以便它可以处理用户传入的数据集.
auto [serif, sansserif, monospace] = get_font_heaps(serif_data, sansserif_data, monospace_data);
auto [comic_sans] = get_font_heaps(comic_sans_data);
Run Code Online (Sandbox Code Playgroud)
我开始试图像这样重写逻辑:
template<typename ... FontDatas>
auto get_font_heaps(std::vector<uint8_t> const& data, FontData&& ...datas) {
if constexpr(sizeof...(FontDatas) == 0) {
return std::make_tuple(get_font_heap_from_data(data));
else {
return std::make_tuple(get_font_heap_from_data(data), get_font_heaps(std::forward<FontDatas>(datas)...);
}
Run Code Online (Sandbox Code Playgroud)
但很明显,即使这个编译,它也不能完全按照我想要的方式执行:它在表单中创建了一个嵌套的元组std::tuple<font_heap, std::tuple<font_heap, std::tuple<font_heap>>>,而我想要的是std::tuple<font_heap, font_heap, font_heap>
我怎样才能重写这个逻辑来做我想做的事情?我正在使用MSVC 2017.3,因此我可以访问许多C++ 17功能,但不能访问Fold Expressions(我怀疑它会大大简化逻辑).