消除模板类不需要的情况
Eliminating the unwanted case for a template class
我使用模板类类型数据类型作为类的方法的参数。在这个方法中,我计算参数的差值并打印出来。这只是一个来自实际项目的示例代码。
Header.h
#ifndef Header_h
#define Header_h
#include <iostream>
#include "string.h"
template <class T>
class Student
{
public:
Student(T);
void calcDifference(int idx, T val1, T val2);
};
#endif
main.cpp
#include <iostream>
#include "Header.h"
using namespace std;
template <class T>
void Student<T>::calcDifference(int idx, T val1, T val2)
{
T difference = val1 - val2;
cout<<"nDifference values: "<<difference<<endl;
}
template <class T>
Student<T>::Student(T)
{
cout<<"constructor called";
}
int main(int argc, const char * argv[])
{
Student<int> oStudent(10);
oStudent.calcDifference(1, 12, 10);
//THIS FOLLOWING OBJECT CREATES ERROR BECAUSE IT IS TRYING TO PASS STRING TYPE
Student<string> o2_Student("hi");
o2_Student.calcDifference(1, "aaa", "aa");
return 0;
}
问题:作为,我试图计算calcDifference()
内部参数之间的差异,main()
中的第二个对象试图传递字符串会产生问题。这是因为差异操作不能在字符串上执行(至少不能直接执行)。
错误: /Users/siddharth/coding/cplusplus/xCode/CPPCodes/InterviewTest/InterviewTest/main.cpp:9:26: Invalid operands to binary expression ('std::__1::basic_string<char>' and 'std::__1::basic_string<char>')
我需要的:我希望代码保持泛型(对于调用函数,我实际上不能改变)。我想找到一些解决方案,这样我就不会得到这个编译器错误,如果传递的参数是字符串类型,那么calcDifference()
应该打印语句(如"不允许字符串数据类型")并返回到调用函数。我可以在calcDifference()
ONLY内进行更改,因为在实际项目中,我无法控制调用函数。我认为异常处理在这种情况下无法帮助,因为它有助于捕获运行时错误,但在这种情况下,我得到编译时错误,因为调用函数试图传递字符串(模板T是字符串)。
PS:我不能在这个结构中做任何改变,这意味着我甚至不能改变参数的数量等。我只能在方法calcDifference()
中进行更改。
T difference = val1 - val2;
当没有为类型定义val1 - val2
时,是一个问题。这是T = std::string
的情况。这就是编译器所抱怨的。
解决这个问题的一种方法是使用辅助struct
模板,它将适用于使用泛型逻辑的大多数类型,但允许您对未定义val1 - val2
的类型进行专门化。
定义一个帮助器struct
template <typename T> struct difference
{
T operator()(T val1, T val2) const { return val1 - val2; }
};
不使用
T difference = val1 - val2;
使用T diff = difference<T>()(val1, val2);
为std::string
专门化difference
。
template <> struct difference<std::string>
{
std::string operator()(std::string const& val1,
std::string const& val2) const
{
// Figure what it means to compute the difference
// between two strings for your application.
return stringDifference(val1, val2);
}
};
我认为有一个非常简单的解决方案:模板专门化。
只需将T
的差异方法的以下专门化添加为string
:
template <>
void Student<string>::calcDifference(
int idx, string const & val1, string const & val2)
{
cout << "Computing string difference (" << val1 << " - " << val2
<< ") is undefined!" << endl;
}
无论何时在string
s上调用calcDifference
,实现的专门化版本是首选的,因此使用。我已经完成了您的示例。这样,您就不需要更改任何调用函数。
进一步注意:我已经添加了一些const &
来处理模板参数。这通常是一个很好的实践,但对于模板来说是必要的:有些传递的T
可能很大,因此仅仅为了计算差异而复制成本很高。
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- 为什么output_editor Concept不需要output_e迭代器标记
- 在除法中不需要四舍五入
- 与C代码相比,为什么C++代码不需要"#define _POSIX_C_SOURCE 200809L"?
- 将值从另一个数组写入数组,不包括不需要的值 C++
- C++ 写入路径名中包含不需要的空字符的文件
- 是否有必要获取锁并在不需要唤醒线程时通知condition_variable?
- 使用 assimp 加载模型 - 不需要提升?
- 如何在不需要LIBCD.lib的情况下在Visual Studio 6中编译C项目
- 为什么在以下情况下不需要为依赖类型使用typename
- Cython:如何在不需要 GIL 的情况下从 numpy 内存视图转到矢量[对[双,双]]?
- 为什么在这种特殊情况下不需要将 std::hash() 的专用化注入到 std 命名空间中?
- 如何在不需要 root 访问权限的情况下为应用程序中的线程设置相对线程优先级
- 如果在不需要的情况下运行语句
- 为什么在这种特殊情况下我不需要模板参数?
- 为什么在某些情况下不需要"std::"?
- 消除模板类不需要的情况
- 为什么在一种情况下模板参数需要volatile,而在另一种情况下不需要
- 如何在不需要实时的情况下制作时间段(这只是模拟)