我有一种情况,我想对模板参数包中的每个值调用一些函数,并将调用该函数的结果存储在堆栈分配的变量中。例如:
#include <string>
#include <utility>
#include <functional>
char const* format_value(double x) { /* ... */ }
std::string format_value(long x) { /* ... */ }
template <typename Sink, typename... Values>
Sink& format(Sink& target, Values... values)
{
// Does not compile; Not valid C++11
typedef std::tuple<typename std::result_of<format_value(values)>::type...> tuple_type;
tuple_type slices(format_value(values)...);
/* Code that does things with the results. */
}
可以进行这种过滤吗?如果可以,我该怎么做?
最佳答案
好的。我看到了your code at github,并希望知道您要实现的目标。
我认为您仍然可以避免对format_buffer()
的递归调用。这是我正在谈论的部分:
template <typename Slice, typename... Slices>
char const* format_buffer(char* ptr, std::size_t length, Slice const& slice, Slices const& ...slices)
{
std::size_t const size = slice.size();
std::copy_n(slice.data(), size, ptr);
return format_buffer(ptr + size, length - size, slices...);
}
template <typename Sink, typename... Slices>
Sink& write_impl(Sink& target, Slices &&...slices)
{
std::size_t const length = sum_sizes(slices...);
OptimisticBuffer<256> buff(length);
char* ptr = buff.GetAs<char>();
char const* endPtr = format_buffer(ptr, length, slices...);
target.append(ptr, endPtr - ptr);
return target;
}
可以替换为:
struct unpack { template<typename ...T> unpack(T && ...) {} };
template <typename Sink, typename... Slices>
Sink& write_impl(Sink& target, Slices &&...slices)
{
std::size_t const length = sum_sizes(slices...);
OptimisticBuffer<256> buff(length);
char* ptr = buff.GetAs<char>();
char *origin = ptr;
unpack { (ptr = std::copy_n(slices.data(), slices.size(), ptr)) ... } ;
target.append(origin, ptr - origin);
return target;
}
魔术发生在
unpack {}
行。对于slice
中的每个slices
,您调用std::copy_n
并返回ptr+size
(然后将其存储在ptr
中),该输入成为下一次对std::copy_n
的调用的输入,依此类推: unpack { (ptr = std::copy_n(slices.data(), slices.size(), ptr)) ... } ;
扩展为:
unpack
{
(ptr = std::copy_n(slices0.data(), slices0.size(), ptr)),
(ptr = std::copy_n(slices1.data(), slices1.size(), ptr)),
(ptr = std::copy_n(slices2.data(), slices2.size(), ptr)),
.
.
(ptr = std::copy_n(slicesN.data(), slicesN.size(), ptr)),
};
请注意,由于它使用列表初始化,因此可以确保表达式的求值顺序是从左到右,即以扩展形式从上到下!
由于GCC has bug since 4.7.0(这就是当前它不起作用的原因),您可以这样编写:
using unpack = void const*[];
unpack {(ptr=std::copy_n(slicesN.data(),slicesN.size(), ptr))...};`
另一个改进是:我将实现
sum_sizes()
而不是sum
,而不是这样: std::size_t const length = sum_sizes(slices...);
我可以这样写:
std::size_t const length = sum(slices.size()...);
这样,
sum()
将更可重用,例如: std::size_t const x = sum(args.get_element_size()...);
std::size_t const y = sum(sizeof(Ts)...);
如果您需要这些。好吧,在
sizeof
的情况下,编译时sum<>
会更好-尽管要点仍然相同,但sum
比sum_sizes()
更可重用。关于c++ - 是否可以从模板参数包构建“过滤的元组”或“过滤的参数包”?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20439495/