带有std::index_sequence的三元操作符
Ternary operator with std::index_sequence
在以下代码中:
#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});
}
如果set.find(Is) == set.end()
,我希望f((set.find(Is) == set.end() ? Is : 2*Is)...);
使用Is
,但没有其他(而不是2*Is
)。因此传递的参数数量是不固定的。如何做到这一点?
对不起,我把问题简化得太多了。下面的代码反映了更真实的问题:
#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<>{});
}
我只是想分享我所寻找的一般问题的解决方案。Barry对上述特定问题的解决方案使之成为可能:
#include <iostream>
#include <utility>
#include <tuple>
template <template <std::size_t, typename> class Check, typename F, size_t... Js, typename Tuple>
void screenArguments (std::index_sequence<>, std::index_sequence<Js...>, const Tuple& tuple) {
F()(std::get<Js>(tuple)...);
}
template <template <std::size_t, typename> class Check, typename F, std::size_t I, size_t... Is, size_t... Js, typename Tuple>
void screenArguments (std::index_sequence<I, Is...>, std::index_sequence<Js...>, const Tuple& tuple) {
if (Check<I, Tuple>::execute(tuple))
screenArguments<Check, F>(std::index_sequence<Is...>{}, std::index_sequence<Js..., I>{}, tuple);
else
screenArguments<Check, F>(std::index_sequence<Is...>{}, std::index_sequence<Js...>{}, tuple);
}
template <template <std::size_t, typename> class Check, typename F, typename Tuple, std::size_t N = std::tuple_size<Tuple>::value>
void passCertainArguments (const Tuple& tuple) {
screenArguments<Check, F> (std::make_index_sequence<N>{}, std::index_sequence<>{}, tuple);
}
// Testing
#include <typeinfo>
template <typename... Args>
void foo (Args&&...) {
std::cout << sizeof...(Args) << " elements passed into foo.n";
}
struct Foo {
template <typename... Args>
void operator()(Args&&... args) {
foo(std::forward<Args>(args)...);
}
};
template <typename... Args>
void bar (Args&&...) {
std::cout << sizeof...(Args) << " elements passed into bar.n";
}
struct Bar {
template <typename... Args>
void operator()(Args&&... args) {
bar(std::forward<Args>(args)...);
}
};
template <std::size_t N, typename Tuple>
struct CheckArguments {
static bool execute (const Tuple& tuple) {
return std::get<N>(tuple) != std::get<N+1>(tuple);
}
};
struct NullObject {};
template <std::size_t N, typename Tuple>
struct CheckNotNullObject {
static bool execute (const Tuple& tuple) {
return typeid(std::get<N>(tuple)) != typeid(NullObject);
}
};
template <typename F, typename... Args>
void executeWithoutNullObject (Args&&... args) {
passCertainArguments<CheckNotNullObject, F> (std::forward_as_tuple(args...));
}
template <typename F, typename... Args>
void executeRemoveConsecutiveRepeatElements (Args&&... args) {
const auto tuple = std::forward_as_tuple(args...);
passCertainArguments<CheckArguments, F, decltype(tuple), sizeof...(Args) - 1> (tuple);
}
int main() {
executeWithoutNullObject<Foo> (3, 5, 'a', true, NullObject{}, 'b', 5.8, NullObject{}, NullObject{}, '!', 2);
// 8 elements passed into foo. (the 3 NullObjects are removed)
executeRemoveConsecutiveRepeatElements<Bar> (2, 1.5, 'a', 'a', true, 5, 5, false);
// 5 elements passed into bar. (the first 'a', the first 5, and 'false' removed)
}
相关文章:
- 如何编写一个使用n倍三元条件语句的C++布尔函数
- 三元运算符和 if constexpr
- 在 c++ 中三元运算符中不允许继续(关键字)吗?
- 三元运算符在返回语句中给出意外的结果
- Boost Spirit x3 条件(三元)运算符解析器
- 为什么用三元初始化类会导致双重释放?
- 如何有效地找到数组中三元组和的最小差异?
- 递归中三元运算符的奇怪行为
- 如何在三元条件运算符中添加换行符和连接? :在 C++ 中
- 错误:三元运算符无法在对象中正常工作"cout"
- 如何重写复杂的c++代码行(嵌套的三元操作符)
- 三元操作符:抛出异常和嵌套
- 带有std::index_sequence的三元操作符
- 使用三元操作符从函数返回统一初始化
- 作为命令的三元操作符
- 使用带return的三元操作符
- 三元操作符的指针转换问题
- c++,三元操作符,std::cout
- 使用三元操作符时出现奇怪的错误
- 为什么三元操作符const我的字符串