问题描述
我正在尝试使用C ++ 14中具有正确数量的参数的函数。我有一个模板类,它基于模板过滤器定义了自身或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':找不到匹配的重载函数”。我在互联网上搜索了几个小时,但现在运气不好了。
有什么方法可以防止评估/丢弃可变参数中要传递的某些参数吗?任何解决方案将不胜感激。
解决方法
我找到了一个解决方案:https://stackoverflow.com/a/36818808/9142528是基于我从未想过的索引序列。它根据预测提供索引序列(对于每种类型,如果该类型的谓词的值为true,则放置该类型的索引,否则为空。)
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);
}