假设我有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也许我走错了路,但我不确定。
这个问题
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);
};
这需要注意,您必须指定所有函数模板参数。
如果你的所有候选者都是相同类型的函数,你可以简单地设置一个本地函数指针数组并从中选择:
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);
};
这里的其他答案已经解释了为什么你的原始方法不起作用的解释。我认为我不能加上......
没有必要使用
using foo = foo_one<T>;
其次是
foo(arg);
你也可以使用
foo_one(arg);
正如您已经注意到的,使用级联if
/ else
语句是一个维护问题,很容易导致错误。
如果你能保留一个可用于调用相应函数的函数/函子的映射会更好。但是,对于函数模板,我认为没有一个明确的常用类型可以用来创建函数/仿函数的映射。
让我们回家其他人有正确的想法表明它可以做到。