我正在尝试编写一些可以处理不同数据类型的通用代码。一旦设置了这些数据类型,则在实例运行期间它将保持不变。
我认为,比起描述,更容易展示我的意图。
helper.h
#include <iostream>
#include <type_traits>
#include <utility>
#include <string>
#include <sstream>
#include <stdexcept>
using namespace std;
template <typename T>
class helper
{
public:
helper()
{
stringstream temp;
if(is_same<T, short>::value)
{
temp << 1;
}
else if(is_same<T,long>::value)
{
temp << 1024;
}
else if(is_same<T, char*>::value)
{
temp << "Hello";
}
else if(is_same<T, string>::value)
{
temp << "Hello World";
}
else
{
throw invalid_argument("Error in helper: Unknown data type" + to_string(__LINE__) + string(__FILE__));
}
temp >> data;
}
T getData()
{
return data;
}
protected:
T data;
};
call.cpp
#include <iostream>
#include "helper.h"
using namespace std;
int main()
{
helper<> my_helper;
int data;
cin >> data;
switch(data)
{
case 1:
my_helper = helper<short>;
break;
case 2:
my_helper = helper<long>;
break;
case 3:
my_helper = helper<char *>;
break;
default:
my_helper = helper<string>;
break;
}
cout << my_helper.getData() << endl;
return 0;
}
现在,由于助手没有模板参数,因此无法编译,但是有一种方法可以在以后的时间点设置参数(例如,在示例中显示用户输入之后) ? 设置了参数后,就不会再有使用情况了。我知道这是一个简单的示例,我可以在其中执行cout
switch-case
,但这是我要完成的概念。
不幸的是,我坚持使用C ++ 11并且没有boost库,否则我认为我可以使用std::any
,我认为可以使用void
指针,但是随后我必须指定调用reinterpret_cast
时数据类型是什么。
如果我可以提供其他信息或可以清除的任何信息,请告诉我!
答案 0 :(得分:2)
helper<short>
是一种类型,而helper<char *>
是另一种完全不兼容的类型。两者均不能分配类型helper<>
。为此,您可以使用基类:
class base {
virtual ~base() = default;
};
template <typename T>
class helper: public base
{
// your code
};
int main()
{
std::unique_ptr<base> my_helper;
int data;
cin >> data;
switch(data)
{
case 1:
my_helper.reset(new helper<short>);
break;
case 2:
my_helper.reset(new helper<long>);
break;
case 3:
my_helper.reset(new helper<char *>);
break;
default:
my_helper.reset(new helper<string>);
break;
}
//cout << my_helper->getData() << endl;
return 0;
}
但是我不认为有一种方法可以在virtual T getData()
中声明base
。
答案 1 :(得分:1)
问题的答案取决于您要实现的目标。 所以第一。不要忘记,模板和OOP通常是正交的。每个模板专长都是与他人无关的新类型。因此,将所有专业转换为相同类型的唯一方法是从一个基类继承。所以
class AbstractHelper
{
public:
virtual ~AbstractHelper() {}
};
template <typename T>
class helper : public AbstractHelper
第二。您需要回答这个问题-模板类的数据可以由单个处理程序处理还是不切实际(基于性能考虑,实现复杂性等),假设它可以(例如,作为字符串)。在这种情况下,您需要:
class AbstractHelper
{
public:
virtual string getDataString() { return ""; }
...
template <typename T>
class helper : public AbstractHelper
{
public:
string getDataString()
{
return to_string(data);
}
如果这不可接受,则需要回答这个问题,是否可以完全封装数据处理?假设可以。然后
class AbstractHelper
{
public:
virtual void printData() { }
...
template <typename T>
class helper : public AbstractHelper
{
public:
void printData()
{
cout << data << endl;;
}
最后,最困难的选择是您需要对所有类型进行不同的处理,并且无法对其进行封装。然后,您需要确定源类型并使用动态类型转换:
enum Type
{
TYPE_SHORT,
TYPE_LONG,
TYPE_STRING
...
class AbstractHelper
{
protected:
Type type_;
public:
Type getType() { return type_; }
......
template <typename T>
class helper : public AbstractHelper
{
public:
helper()
{
stringstream temp;
if (is_same<T, short>::value)
{
temp << 1;
type_ = TYPE_SHORT;
}
else if (is_same<T, long>::value)
{
temp << 1024;
type_ = TYPE_LONG;
}
...
并选择所需的处理程序:
switch (my_helper.getType())
{
case TYPE_SHORT:
cout << dynamic_cast<helper<short>&>(my_helper).getData() << endl;
break;
case TYPE_LONG:
cout << dynamic_cast<helper<long>&>(my_helper).getData() << endl;
请不要对手动代码的数量感到困惑-宏和模板可以大大减少它。