C++根据模板参数的类型有条件地调用函数
C++ conditionally call functions based on type of the template parameter
假设我有几个函数来处理不同类型的参数。例如,processInt
用于处理int
变量,processString
用于处理std::string
变量。
int processInt(int i)
{
return i;
}
string processString(string s)
{
return s;
}
而且,我有一个名为foo
的模板函数,它将int
或std::string
中的任何一个作为参数。在这个函数中,我需要根据作为参数发送给它的变量类型有条件地调用processInt
或processString
。foo
函数如下所示:
#include <type_traits>
template<typename T>
T foo(T value)
{
T variable;
if (std::is_same<T, int>::value)
{
variable = processInt(value);
}
else if (std::is_same<T, string>::value)
{
variable = processString(value);
}
return variable;
}
int main() {
string s = "Abc";
int i = 123;
cout << foo(s) << " " << foo(i) << endl;
}
但是,使用上述foo
函数,我收到以下错误:
error: no matching function for call to 'processInt'
variable = processInt(value);
^~~~~~~~~~
note: in instantiation of function template specialization 'foo<std::__cxx11::basic_string<char> >' requested here
cout << foo(s) << " " << foo(i) << endl;
^
note: candidate function not viable: no known conversion from 'std::__cxx11::basic_string<char>' to 'int' for 1st argument
int processInt(int i)
^
error: no matching function for call to 'processString'
variable = processString(value);
^~~~~~~~~~~~~
note: in instantiation of function template specialization 'foo<int>' requested here
cout << foo(s) << " " << foo(i) << endl;
^
note: candidate function not viable: no known conversion from 'int' to 'std::__cxx11::string' (aka 'basic_string<char>') for 1st argument
string processString(string s)
^
源代码:https://godbolt.org/z/qro8991ds
如何正确执行此操作以根据泛型函数中模板参数的类型有条件地调用函数?
编辑
我喜欢使用单个foo
函数而不重载或专业化,否则可能会有一些代码重复。foo
函数可能有很多行。但是,int
和string
代码之间的差异将是一行。
对于这样的事情,我会建议模板和专业化:
// Declare base template
template<typename T>
T process(T);
// Specialization for integers
template<>
int process(int value)
{
// ... code to process integers...
}
// Specialization for strings
template<>
std::string process(std::string value)
{
// ... code to process strings...
}
然后foo
函数简单地变成
template<typename T>
T foo(T value)
{
return process(value);
}
可选的普通旧重载也应该正常工作。
所有分支都应该有效,即使分支未被占用。 C++17 有if constexpr
可以解决您的问题
template<typename T>
T foo(T value)
{
T variable;
if constexpr (std::is_same<T, int>::value)
{
variable = processInt(value);
}
else if constexpr (std::is_same<T, string>::value)
{
variable = processString(value);
}
return variable;
}
对于c++17 之前的格式,您可以使用重载来获得类似的结果(对于更复杂的情况,标记调度):
int foo(int value)
{
return processInt(value);
}
std::string foo(const std::string& value)
{
return processString(value);
}
template <typename T
// possibly some SFINAE to allow some conversion with above functions
/*, std::enable_if_t<std::is_constructible<std::string, T>, bool> = true */>
T foo(T value)
{
return T{};
}
在 C++17 中,您可以使用立即调用的 lambda 和if constexpr
来执行此操作
template<typename T>
T foo(T value) {
auto variable = [&value]{
if constexpr (std::is_same_v<T, int>)
return processInt(value);
else if constexpr (std::is_same_v<T, std::string>)
return processString(value);
}();
// use variable
return variable;
}
演示
相关文章:
- C++有多少类型的循环
- 具有条件类型名的模板类
- 如何使用 soong 命名空间来有条件地编译模块
- 有条件地将默认参数传递给函数(使用"?"运算符)
- 我的代码中是否有任何类型的错误,因为它没有给出正确的输出
- 根据模板类型有条件地删除变量
- 有条件地选择带有 decltype() 和三元运算符的类型
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 有没有一种很好的方法来实现具有默认失败情况的条件类型?
- C 模板:如何根据数据类型有条件编译不同的代码
- 根据成员变量的类型是否存在,有条件地定义该变量
- 如果类型(不)相等,是否可以C++有条件地编译代码?
- 有条件地从函数返回对象类型
- 警告 634:相等或有条件的强类型不匹配(类型"bool")
- 如何有条件地编译返回类型的模板化函数
- 如何在给定指向派生类型的指针的情况下有条件地将指针强制转换为基类型
- 有条件返回不同类型的c++函数
- 有条件地启用子类型(类似于启用函数的enable_if)
- 编写泛型包装器:有条件地将模板参数中的不同类型映射到单个类内部类型
- 有条件地从模板函数返回不同类型的正确方法