C++ 具有std::index_序列的三元运算符
在以下代码中:C++ 具有std::index_序列的三元运算符,c++,templates,c++11,variadic,C++,Templates,C++11,Variadic,在以下代码中: #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 (st
#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});
}
由于三元运算符传递的混合类型,上面的代码无法编译,但我想您可以在这里看到我的想法。如果条件std::gettuple!=std::gettuple,因此我传递NullObject{},然后尝试从f的参数中删除所有NullObjects,以获得传递给f的真正参数。对此不能使用三元运算符-这需要两个具有公共类型的表达式。这里没有骰子。我不知道如何根据运行时比较有条件地返回不同的类型 您必须有条件地将类型转发到另一个函数,只需引入另一个构建参数的助手函数。。。还有一个简单的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<>{});
}
不能为此使用三元运算符-这需要两个具有公共类型的表达式。这里没有骰子。我不知道如何根据运行时比较有条件地返回不同的类型 您必须有条件地将类型转发到另一个函数,只需引入另一个构建参数的助手函数。。。还有一个简单的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)
}
我只是想分享我所寻求的一般问题的解决方案。通过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)
}
你不能,不能用三元表达式。为什么不使用if语句呢?或者在三元表达式中调用f函数,而不是在f调用中使用三元表达式。如果可以通过编译类型替换std::set内容,则可以执行如下操作:@Jarod42抱歉,我将问题简化得太多,并更新了问题。我不确定你的技术是否仍然适用。@prestokeys:如果你在std::integral_常量的帮助下将运行时变量转换为类型,你可以正确调用f,但无论如何它都需要帮助函数。你不能,三元表达式不行。为什么不使用if语句呢?或者在三元表达式中调用f函数,而不是在f调用中使用三元表达式。如果可以通过编译类型替换std::set内容,则可以执行如下操作:@Jarod42抱歉,我将问题简化得太多,并更新了问题。我不确定您的技术是否仍然适用。@prestokeys:如果您在std::integral_常量的帮助下将运行时变量转换为类型,您可以正确调用f,但无论如何它都需要帮助函数。@Barry抱歉,我简化了太多问题,并更新了问题。我不确定您的技术是否仍然适用。@prestokeys确定,只需调用fstd::gettuple。。。相反,我想。@Barry是的,我试过了,并在我的问题中发布了它,但它并没有编译超出范围错误的元组元素索引。虽然我认为这是可以解决的。更新:已修复。谢谢。@prestokeys它无法编译,因为您正在传递make_index_序列{}。您的元组大小为8,并且您正在比较连续的元素,因此您希望传入make_index_序列。@Barry抱歉,我将问题简化得太多,并更新了问题。我不确定您的技术是否仍然适用。@prestokeys确定,只需调用fstd::gettuple。。。相反,我想。@Barry是的,我试过了,并在我的问题中发布了它,但它并没有编译超出范围错误的元组元素索引。虽然我认为这是可以解决的。更新:已修复。谢谢。@prestokeys它无法编译,因为您正在传递make_index_序列{}。您的元组大小为8,并且您正在比较连续的元素,因此您希望传入make\u index\u序列。