在下面的代码中:
#include <iostream>
#include <utility>
#include <set>
template <typename... Args>
void f(Args... args) {
std::cout << sizeof...(Args) << " elements.\n";
}
template <std::size_t... Is>
void g (std::index_sequence<Is...>, const std::set<int>& set) {
f((set.find(Is) == set.end() ? Is : 2*Is)...);
}
int main() {
g (std::make_index_sequence<10>{}, {1,3,7,8});
}
我要f((set.find(Is) == set.end() ? Is : 2*Is)...);
使用 Is
如果set.find(Is) == set.end()
但没有别的(而不是 2*Is
)。因此传递的参数数量是不固定的。如何实现?
编辑: 抱歉,我把问题简单化了太多。下面的代码更能反射(reflect)真正的问题:
#include <iostream>
#include <utility>
#include <tuple>
template <typename... Args>
void f(Args... args) {
std::cout << sizeof...(Args) << " elements.\n";
}
struct NullObject {};
template <typename Tuple, std::size_t... Is>
void g (std::index_sequence<Is...>, const Tuple& tuple) {
f ((std::get<Is>(tuple) != std::get<Is+1>(tuple) ? std::get<Is>(tuple) : NullObject{})...);
}
int main() {
g (std::make_index_sequence<8>{}, std::make_tuple(2,1.5,'a','a',true,5,5,false));
}
由于三元运算符传递的混合类型,上面的代码无法编译,但我想你可以在这里看到我的想法。如果条件 std::get<Is>(tuple) != std::get<Is+1>(tuple)
,我想传递 NOTHING ,所以我改为通过 NullObject{}
然后以某种方式尝试从 f
的参数中删除所有 NullObjects获取传递给 f
的真实参数.
最佳答案
您不能为此使用三元运算符 - 这需要两个具有共同类型的表达式。这里没有骰子。我知道无法根据运行时 比较有条件地返回不同的类型。
您必须有条件地将类型转发给不同的函数,方法是引入另一个构建 Args...
的辅助函数和一个简单的 if
声明:
template <size_t... Js>
void fhelper (std::index_sequence<>, const std::set<int>& , std::index_sequence<Js...>) {
f(Js...);
}
template <std::size_t I, size_t... Is, size_t... Js>
void fhelper (std::index_sequence<I, Is...>, const std::set<int>& set, std::index_sequence<Js...>) {
if (set.find(I) == set.end()) {
fhelper(std::index_sequence<Is...>{}, set, std::index_sequence<Js..., I>{});
}
else {
fhelper(std::index_sequence<Is...>{}, set, std::index_sequence<Js...>{});
}
}
int main() {
fhelper (std::make_index_sequence<10>{}, {1,3,7,8}, std::index_sequence<>{});
}
关于c++ - 带 std::index_sequence 的三元运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32822565/