模板化函数范围内的条件模板化类型别名
Conditional templated type aliases in scope of templated function
假设我有N
函数,它们有一组相同的参数。 我调用带有参数的工厂方法,以及一些允许我在N
函数之间进行选择的值。
一种不整洁的方法是像这样做一个 if 语句:
if(choice == 1)
foo_one<T>(args);
else if (choice == 2)
foo_two<T>(args);
etc
这很好,除了在我的情况下,参数数量很大。 因此,工厂方法非常拥挤。
假设我有一个调用工厂方法的主函数:
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_onen"; };
template <typename T>
void foo_two(T arg) { std::cout << "foo_onen"; };
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
存在于函数范围之外。
这个问题表明我可能走错了路,但我不确定。
问题
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
超出范围并且您会收到错误。 您可以获取指向函数的指针,而不是获取函数的别名,然后在末尾调用指针。 那嘟嘟看起来像
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
语句是一个维护问题,很容易导致错误。
如果您可以保留可用于调度对相应函数的调用的函数/函子映射,那就更好了。但是,对于函数模板,我认为没有明确的通用类型可用于创建函数/函子映射。
让我们回家,其他人有正确的想法来证明这是可以做到的。
相关文章:
- 继承模板类中的类型别名
- 为什么 GCC 在使用类型别名时处理 const reinterpret_cast不同?
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 如何使用类型别名从模板化类中隐藏模板列表
- 如何检测类型类型别名?
- C++类型别名,其中值被替换
- 如何为流输出运算符提供重载<<模板'using'类型别名?
- 通过类型别名从构造函数转发模板推导
- C++中的严格别名规则和类型别名
- 使用其他模板类型参数作为要在函数签名中使用的类型别名声明
- 什么是C++中的类型别名?
- 如何在不违反类型别名规则的情况下解释消息负载?
- 在模板派生类中继承具有类型别名的构造函数
- 类型别名允许分配任意指针,尽管 int* 是必需的
- 使用类型别名,例如使用 A = int(int)
- 模板类函数指针类型别名
- 类型别名和类似类型
- 泛型类型别名,它们彼此不兼容
- 具有类型别名的循环依赖项
- 为什么模板引用类型不能用作模板类型别名参数?