【问题标题】:Skip void arguments跳过无效参数
【发布时间】:2020-09-11 09:10:19
【问题描述】:

我正在尝试在 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.我在互联网上搜索了几个小时,现在我运气不好。

有什么方法可以防止评估/丢弃来自要传递的可变参数的某些参数?任何解决方案将不胜感激。

【问题讨论】:

  • 第一种方法有什么问题?如果您在类定义后添加分号,则此代码有效:int i = 5; shouldPassComponent&lt;int&gt; spc1; spc1((int*) &amp;i); shouldPassComponent&lt;exclude&lt;int&gt;&gt; spc2; spc2((int*) &amp;i);

标签: c++ arguments c++14 void template-specialization


【解决方案1】:

我找到了一个解决方案: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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-20
    • 2015-11-20
    • 2016-07-07
    • 2018-11-19
    • 1970-01-01
    • 2020-12-03
    • 2015-08-24
    • 2019-01-31
    相关资源
    最近更新 更多