跳过无效参数

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);
}