跳过无效参数
Skip void arguments
我正在尝试在 C++14 中调用具有正确数量参数的函数。我有一个模板 class,它基于模板过滤器定义了自身或 void 的别名:要么跳过参数,要么传递参数,如下所示:
template<typename comp>
struct exclude {};
template<typename comp>
struct shouldPassComponent
{
using type = comp;
comp& operator()(comp* component) { return *component; }
const comp& operator()(const comp* component) const { return *component; }
}
// void is aliased instead of the component
template<typename comp>
struct shouldPassComponent<exclude<comp>>
{
using type = void;
void operator()(comp* component) {}
void operator()(const comp* component) const {}
}
// if void, the argument should be skipped/not evaluated instead
std::invoke(func, shouldPassComponent<types>()(comps)...); // error here
不幸的是,它不起作用,因为编译器仍然计算参数中的“void()”(错误:“未找到匹配的重载函数”)。
所以我尝试了非模板方式,看看它是否可行:
void CallFunction();
CallFunction(void()); // error here
但是,编译器出现错误:“错误 C2672:CallFunction:未找到匹配的重载函数”。所以我想到了 lambda 接受自动参数的事实:
void CallFunction();
auto lambdaTest = [](auto... Arguments)
{
//....
CallFunction(Arguments...);
};
lambdaTest(void()); // error here
调用 lambdaTest 时,编译器仍然出现错误:“错误 C2672:'operator __surrogate_func':未找到匹配的重载函数”。我在 Internet 上搜索了几个小时,现在我倒霉了。
有什么方法可以防止 evaluating/discarding 可变参数的某些参数被传递?任何解决方案将不胜感激。
我找到了一个解决方案:它基于一个我从未想过的索引序列。它根据预测提供索引序列(对于每种类型,如果该类型的谓词值为真,则放置该类型的索引,否则没有)。
template<typename component>
struct exclude {};
template<typename component>
struct isResolvable
{
enum { value = true };
};
template<typename component>
struct isResolvable<exclude<component>>
{
enum { value = false };
};
template<typename...components>
struct view_t
{
template<typename component>
struct component_t
{
using type = component;
};
template<typename component>
struct component_t<exclude<component>>
{
using type = component;
};
template<typename funcType>
static void call(funcType func, typename component_t<components>::type&... comps)
{
callImpl(func, std::make_tuple((&comps)...), find_indices<isResolvable, components...>{});
}
template<typename funcType, typename...components, size_t...Is>
static void callImpl(funcType func, const std::tuple<components*...>& tuple, std::index_sequence<Is...>)
{
std::invoke(func, *std::get<Is>(tuple)...);
}
};
struct test1 {};
struct test2 {};
void testCallback(test1& comp)
{
}
void test()
{
test1 comp1;
test2 comp2;
view_t<test1, exclude<test2>>::call(&testCallback, comp1, comp2);
}
我正在尝试在 C++14 中调用具有正确数量参数的函数。我有一个模板 class,它基于模板过滤器定义了自身或 void 的别名:要么跳过参数,要么传递参数,如下所示:
template<typename comp>
struct exclude {};
template<typename comp>
struct shouldPassComponent
{
using type = comp;
comp& operator()(comp* component) { return *component; }
const comp& operator()(const comp* component) const { return *component; }
}
// void is aliased instead of the component
template<typename comp>
struct shouldPassComponent<exclude<comp>>
{
using type = void;
void operator()(comp* component) {}
void operator()(const comp* component) const {}
}
// if void, the argument should be skipped/not evaluated instead
std::invoke(func, shouldPassComponent<types>()(comps)...); // error here
不幸的是,它不起作用,因为编译器仍然计算参数中的“void()”(错误:“未找到匹配的重载函数”)。
所以我尝试了非模板方式,看看它是否可行:
void CallFunction();
CallFunction(void()); // error here
但是,编译器出现错误:“错误 C2672:CallFunction:未找到匹配的重载函数”。所以我想到了 lambda 接受自动参数的事实:
void CallFunction();
auto lambdaTest = [](auto... Arguments)
{
//....
CallFunction(Arguments...);
};
lambdaTest(void()); // error here
调用 lambdaTest 时,编译器仍然出现错误:“错误 C2672:'operator __surrogate_func':未找到匹配的重载函数”。我在 Internet 上搜索了几个小时,现在我倒霉了。
有什么方法可以防止 evaluating/discarding 可变参数的某些参数被传递?任何解决方案将不胜感激。
我找到了一个解决方案:它基于一个我从未想过的索引序列。它根据预测提供索引序列(对于每种类型,如果该类型的谓词值为真,则放置该类型的索引,否则没有)。
template<typename component>
struct exclude {};
template<typename component>
struct isResolvable
{
enum { value = true };
};
template<typename component>
struct isResolvable<exclude<component>>
{
enum { value = false };
};
template<typename...components>
struct view_t
{
template<typename component>
struct component_t
{
using type = component;
};
template<typename component>
struct component_t<exclude<component>>
{
using type = component;
};
template<typename funcType>
static void call(funcType func, typename component_t<components>::type&... comps)
{
callImpl(func, std::make_tuple((&comps)...), find_indices<isResolvable, components...>{});
}
template<typename funcType, typename...components, size_t...Is>
static void callImpl(funcType func, const std::tuple<components*...>& tuple, std::index_sequence<Is...>)
{
std::invoke(func, *std::get<Is>(tuple)...);
}
};
struct test1 {};
struct test2 {};
void testCallback(test1& comp)
{
}
void test()
{
test1 comp1;
test2 comp2;
view_t<test1, exclude<test2>>::call(&testCallback, comp1, comp2);
}