模板化函数范围内的条件模板类型别名

问题描述 投票:0回答:3

假设我有N函数,它们有一组参数。我使用参数调用工厂方法,并允许我在N函数之间进行选择。

一个不整洁的方法是像这样做一个if语句:

if(choice == 1)
    foo_one<T>(args);
else if (choice == 2)
    foo_two<T>(args);
etc

这很好,除了在我的情况下,参数的数量很大。因此工厂方法非常拥挤。

假设我有一个调用工厂方法的main函数:

int main(int argc, char *argv[])
{
    int choice = 1;
    float arg = 1.5;
    foo_choose(choice, arg);
    return 0;
}

我正在考虑在choice参数上进行分支,并在if语句中设置函数别名。

这意味着我只需要传递一次我的论点,无论N有多大。

它可能看起来像这样:

template <typename T>
void foo_one(T arg) { std::cout << "foo_one\n"; };

template <typename T>
void foo_two(T arg) { std::cout << "foo_one\n"; };

template <typename T>
void foo_choose(int choice, T arg)
{
    if(choice == 1)
        using foo = foo_one<T>;
    else
        using foo = foo_two<T>;        

    foo(arg);
};

但是,我无法使用模板。是否有一些明显我缺失的东西,或者我应该添加的搜索词。

因为我可能会用foo_choose的不同值多次调用choice,所以我不希望别名foo存在于函数范围之外。

This question suggests也许我走错了路,但我不确定。

c++ templates alias
3个回答
2
投票

这个问题

template <typename T>
void foo_choose(int choice, T arg)
{
    if(choice == 1)
        using foo = foo_one<T>;
    else
        using foo = foo_two<T>;        

    foo(arg);
};

是using语句是作用域语句。这意味着它们只适用于声明的范围,一旦你到达foo(arg);foo超出范围并且你得到一个错误。您可以获取指向它的指针,然后在结尾处调用指针,而不是获取该函数的别名。那个woudls看起来像

template <typename T>
void foo_choose(int choice, T arg)
{
    using f_ptr = void(*)(T);
    f_ptr foo;
    if(choice == 1)
        foo = foo_one<T>;
    else
        foo = foo_two<T>;        

    foo(arg);
};

这需要注意,您必须指定所有函数模板参数。


1
投票

如果你的所有候选者都是相同类型的函数,你可以简单地设置一个本地函数指针数组并从中选择:

template <typename T>
void foo_choose(int choice, T arg)
{
    constexpr void (*funcs[])(T) = { foo_one<T>, foo_two<T> };

    assert(choice > 0 && choice < std::extent_v<decltype(funcs)>);

    return funcs[choice](arg);
};

live example here

这里的其他答案已经解释了为什么你的原始方法不起作用的解释。我认为我不能加上......


0
投票

Minor point

没有必要使用

using foo = foo_one<T>;

其次是

foo(arg);

你也可以使用

foo_one(arg);

More important

正如您已经注意到的,使用级联if / else语句是一个维护问题,很容易导致错误。

如果你能保留一个可用于调用相应函数的函数/函子的映射会更好。但是,对于函数模板,我认为没有一个明确的常用类型可以用来创建函数/仿函数的映射。

让我们回家其他人有正确的想法表明它可以做到。

© www.soinside.com 2019 - 2024. All rights reserved.