Ios*_*ber 12 c++ variadic-functions c++11
假设我有类型A
,B
有构造函数A(int a, double b, std::string c)
,B(double a, int b)
.
我知道如何定义一个实例化A
或B
通过可变参数模板的函数.
有没有办法设计一个函数/宏/类型,对于一个类型T
和一系列T
构造函数参数的可能性向量,它为我提供了所有可能的对象?
例如,如果我使用这个神奇的构造,<A, {2, 5, 6}, {2.44, 3.14}, {"yes", "no"}>
它应该提供对象:
A(2, 2.44, "yes")
A(2, 2.44, "no")
A(2, 3.14, "yes")
...
A(6, 3.14, "no")
Run Code Online (Sandbox Code Playgroud)
这同样适用于B
任何其他类型,而不必重新设计魔法结构.
例如,这在Python中非常简单,但我不知道它是否可以在C++中使用.
这std::experimental::array_view
用于提高效率.您可以std::vector
以某些运行时成本替换它,或以一定的清晰度成本替换一对迭代器/指针.
template<class T>
using array_view = std::experimental::array_view<T>;
using indexes = array_view<std::size_t>;
Run Code Online (Sandbox Code Playgroud)
这会迭代每个元素的交叉积,<
索引中的相应索引.因此,{3,3,2}
如is
在迭代{0,0,0}
然后{0,0,1}
一路{2,2,1}
.
template<class F>
void for_each_cartesian_product(
indexes is,
F&& f,
std::vector<std::size_t>& result
) {
if (is.empty()) {
f(result);
return;
}
auto max_index = is.front();
for (std::size_t i = 0; i < max_index; ++i) {
result.push_back(i);
for_each_cartesian_product( {is.begin()+1, is.end()}, f, result );
result.pop_back();
}
}
template<class F>
void for_each_cartesian_product(
indexes is,
F&& f
) {
std::vector<size_t> buffer;
for_each_cartesian_product( is, f, buffer );
}
Run Code Online (Sandbox Code Playgroud)
然后我们只填充我们的索引:
template<class...Ts>
std::vector<std::size_t> get_indexes( std::vector<Ts> const&... vs ) {
return {vs.size()...};
}
Run Code Online (Sandbox Code Playgroud)
接下来,我们可以只需要接受我们的参数,将它们放在一个向量中,然后使用索引从每个向量中获取元素并将它们传递A
给构造.
template<class T, std::size_t...Is, class...Args>
std::vector<T> make_stuff( std::index_sequence<Is...>, std::vector<Args>const&... args ) {
std::vector<T> retval;
for_each_cartesian_product(
get_indexes(args...),
[&](auto&& index){
retval.emplace_back( args[ index[Is] ]... );
}
);
return retval;
}
template<class T, class...Args>
std::vector<T> make_stuff( std::vector<Args>const&... args ) {
return make_stuff<T>( std::index_sequence_for<Args...>{}, args... );
}
Run Code Online (Sandbox Code Playgroud)
和鲍勃是你的叔叔.
A
生成的s可以移动.
在编译时使用编译时已知数组执行此操作也可以完成.
index_sequence_for
并且index_sequence
是C++ 14,但很容易在C++ 11中实现.堆栈溢出有很多例子.
上面的代码尚未编译.
归档时间: |
|
查看次数: |
284 次 |
最近记录: |