在以后的时间点确定模板类型 C++
Determining a template type at later point in time C++
我想尝试编写一些可以处理不同数据类型的通用代码。一旦设置了这些数据类型,它就会在整个实例期间保持不变。
我认为展示我正在尝试做的事情比描述它更容易。
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;
}
现在,这不会编译,因为 helper 没有模板参数,但是有没有办法让我可以在稍后的时间点设置参数(比如在有用户输入之后,如例子)? 一旦设置了参数,就不会改变它的用例。我知道这是一个简单的例子,我可以只是做一个cout
中的switch-case
,但这是我要完成的概念。
不幸的是我坚持使用 C++11 并且没有增强库,否则我想我可以使用 std::any
,我想我可以使用 void
指针,但是我会指定调用 reinterpret_cast
.
时的数据类型
如果有任何我可以提供的额外信息或任何我可以解决的问题,请告诉我!
helper<short>
是一种类型,helper<char *>
是另一种完全不兼容的类型。没有类型 helper<>
可以由两者分配。为此,您可以使用基数 class:
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;
}
但是我认为没有办法在 base
中声明 virtual T getData()
。
您问题的答案取决于您要实现的目标。
所以第一个。不要忘记模板和 OOP 通常是正交的。每个模板特化都是一种与其他模板不相关的新类型。因此,将所有特化转换为同一类型的唯一方法是从一个基础继承 class。所以
class AbstractHelper
{
public:
virtual ~AbstractHelper() {}
};
template <typename T>
class helper : public AbstractHelper
其次。您需要回答这个问题 - 您的模板 classes 的数据可以由单个处理程序处理还是不切实际(基于性能考虑、实现复杂性等)假设它可以,例如作为字符串。在这种情况下,您需要:
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;
}
...
和select所需的处理程序:
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;
不要对手动代码的数量感到困惑 - 宏和模板可以显着减少它。
我想尝试编写一些可以处理不同数据类型的通用代码。一旦设置了这些数据类型,它就会在整个实例期间保持不变。
我认为展示我正在尝试做的事情比描述它更容易。
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;
}
现在,这不会编译,因为 helper 没有模板参数,但是有没有办法让我可以在稍后的时间点设置参数(比如在有用户输入之后,如例子)? 一旦设置了参数,就不会改变它的用例。我知道这是一个简单的例子,我可以只是做一个cout
中的switch-case
,但这是我要完成的概念。
不幸的是我坚持使用 C++11 并且没有增强库,否则我想我可以使用 std::any
,我想我可以使用 void
指针,但是我会指定调用 reinterpret_cast
.
如果有任何我可以提供的额外信息或任何我可以解决的问题,请告诉我!
helper<short>
是一种类型,helper<char *>
是另一种完全不兼容的类型。没有类型 helper<>
可以由两者分配。为此,您可以使用基数 class:
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;
}
但是我认为没有办法在 base
中声明 virtual T getData()
。
您问题的答案取决于您要实现的目标。 所以第一个。不要忘记模板和 OOP 通常是正交的。每个模板特化都是一种与其他模板不相关的新类型。因此,将所有特化转换为同一类型的唯一方法是从一个基础继承 class。所以
class AbstractHelper
{
public:
virtual ~AbstractHelper() {}
};
template <typename T>
class helper : public AbstractHelper
其次。您需要回答这个问题 - 您的模板 classes 的数据可以由单个处理程序处理还是不切实际(基于性能考虑、实现复杂性等)假设它可以,例如作为字符串。在这种情况下,您需要:
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;
}
...
和select所需的处理程序:
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;
不要对手动代码的数量感到困惑 - 宏和模板可以显着减少它。