C++ C++;如何在泛型编程中声明自定义数组
我有一个类模板C++ C++;如何在泛型编程中声明自定义数组,c++,templates,generic-programming,C++,Templates,Generic Programming,我有一个类模板 template <class T> class Collection { private: int size; int type; T* Arr; int Case; public: void ArrayGenerating() { switch(type) { case 1: Arr = new T[size]; for (int i = 0; i < size; i++
template <class T> class Collection
{
private:
int size;
int type;
T* Arr;
int Case;
public:
void ArrayGenerating() {
switch(type) {
case 1:
Arr = new T[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast <T> (rand()) % size;
}
case 2:
Arr = new T[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast <T> (rand()) / (static_cast <T> (RAND_MAX/size));
}
case 3:
Arr = new T[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i].setNumerator(static_cast <int> (rand()) % size);
srand((unsigned)time(NULL));
Arr[i].setDenominator(static_cast <int> (rand()) % size);
}
}
}
};
那么,如果有什么办法可以解决这个问题呢?你为什么要这样做,让你的生活变得更加困难? 可以这么简单:
#include <iostream>
#include <chrono>
#include <random>
template<class type_t, std::size_t size>
class Array
{
private:
type_t arr[size];
public:
Array()
{
for (std::size_t i = 0; i < size; ++i)
{
//nice C++ random number generation
auto seed = static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
std::minstd_rand0 randm(seed);
arr[i] = randm();
}
}
//test function
void print()
{
for (int i = 0; i < size; ++i)
std::cout << arr[i] << " ";
}
};
int main()
{
Array<int, 4> arr;
arr.print();
std::cin.get();
}
#包括
#包括
#包括
模板
类数组
{
私人:
类型_t arr[尺寸];
公众:
数组()
{
对于(标准::大小\u t i=0;i
类模板中的类型
成员在某种程度上违背了泛型编程的目的,不是吗?你应该摆脱类型
,用模板专业化取代开关
下面是一个简单的示例,让您开始学习:
// Collection for all T except of `fraction`
template <class T> class Collection
{
private:
int size;
T* Arr;
int Case;
public:
void ArrayGenerating() {
Arr = new T[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast <T> (rand()) % size;
}
};
};
// Collection for `fraction`
template <> class Collection<fraction>
{
private:
int size;
fraction* Arr;
int Case;
public:
void ArrayGenerating() {
Arr = new fraction[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i].setNumerator(static_cast <int> (rand()) % size);
srand((unsigned)time(NULL));
Arr[i].setDenominator(static_cast <int> (rand()) % size);
}
}
};
//除“分数”之外的所有T的集合`
模板类集合
{
私人:
整数大小;
T*Arr;
int-Case;
公众:
void数组生成(){
Arr=新T[尺寸];
对于(int i=0;i
这是一种最简单的模板专业化,但可能会导致大量的代码重复。不过,您也可以绕过这个问题。例如,您可以将所有公共部分提取到一个公共私有基类中,如下所示:
namespace detail
{
template <class T> class CollectionBase
{
protected:
int size;
T* Arr;
int Case;
};
}
template <class T> class Collection : detail::CollectionBase<T>
{
public:
void ArrayGenerating() {
Base::Arr = new T[Base::size];
for (int i = 0; i < Base::size; i++) {
srand((unsigned)time(NULL));
Base::Arr[i] = static_cast <T> (rand()) % Base::size;
}
};
private:
using Base = detail::CollectionBase<T>;
};
template<> class Collection<fraction> : detail::CollectionBase<fraction>
{
public:
void ArrayGenerating() {
Base::Arr = new fraction[Base::size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i].setNumerator(static_cast <int> (rand()) % size);
srand((unsigned)time(NULL));
Arr[i].setDenominator(static_cast <int> (rand()) % size);
}
}
private:
using Base = detail::CollectionBase<fraction>;
};
名称空间详细信息
{
模板类集合库
{
受保护的:
整数大小;
T*Arr;
int-Case;
};
}
模板类集合:detail::CollectionBase
{
公众:
void数组生成(){
Base::Arr=新的T[Base::size];
对于(int i=0;i
通常,请阅读更多有关模板专业化的信息,您一定会找到正确的解决方案:
我想,type
是一个常数,取决于T。否则,当T是浮点时,将T*点指向int是没有意义的。如果这是真的,则根本没有必要
我认为,您需要的是模板专门化(未经测试的代码):
现在我们实现了一个类似于您的集合
类模板,如果我们仍然需要它:
template <typename T> Collection {
private:
// this will handle all your memory management needs
std::vector<T> randoms;
public:
Collection(size_t s) :
randoms{createRandomNumbers<T>(s)}
{};
createNewRandoms(size_t s) {
std::swap(randoms, createRandomNumbers<T>(s));
};
// whatever else is necessary
};
模板集合{
私人:
//这将满足您所有的内存管理需求
向量随机数;
公众:
收集(大小):
随机数{createRandomNumbers(s)}
{};
createNewRandoms(大小){
交换(随机数,创建随机数);
};
//还有什么必要的吗
};
看起来您想对生成函数使用模板专门化。在其他新闻中,不要在循环中调用srand
,不要将分母设置为rand()%size
除非分数数据类型允许零分母,并且不要使用单独的整数类型
选择器,因为所有信息都已包含在t
模板参数中。不要伤害自己:使用向量
、
和
。有人建议您使用模板专用化,您应该这样做。但是,如果您想从长远来看为自己省去一些麻烦,请尝试将依赖类型的操作隔离到函数中,然后使用traits类提供的操作。其他一些小的改进将使用std::array
和基于范围的for
循环。是的,std::array
甚至可以消除需要编写我们自己的类。
// this is common to all cases.
class CollectionBase {
protected:
int size;
};
// the general template is not defined
// the compiler will complain whenever T is neither int, nor float, nor fraction.
template<class T> class Collection;
// here come the specializations
template<> class Collection<int>: private CollectionBase
{
private:
int* Arr;
public:
void ArrayGenerating() {
Arr = new int[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast<int>(rand()) % size;
}
}
};
template<> class Collection<float>: private CollectionBase
{
private:
float* Arr;
public:
void ArrayGenerating() {
Arr = new float[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast<float>(rand()) / (static_cast<float>(RAND_MAX/size));
}
}
};
template<> class Collection<fraction>: private CollectionBase
{
private:
fraction* Arr;
public:
void ArrayGenerating() {
Arr = new fraction[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i].setNumerator(static_cast <int> (rand()) % size);
srand((unsigned)time(NULL));
Arr[i].setDenominator(static_cast <int> (rand()) % size);
}
}
};
template<typename T> struct dist{
using uniform = std::uniuniform_int_distribution<T>;
};
template<> struct dist<float> {
using uniform = std::uniuniform_real_distribution<float>;
};
template<typename T>
std::vector<T> createRandomNumbers(size_t s) {
auto e1 = std::default_random_engine{std::random_device{}()};
auto u = dist<T>::uniform{0, static_cast<T>(s)};
auto r = std::vector<T>(s, 0);
for( auto& i: r ) i = u(e1);
return r;
}
// fraction need a specialization
template<>
std::vector<fraction> createRandomNumbers<fraction>(size_t s) {
auto e1 = std::default_random_engine{std::random_device{}()};
auto u = dist<int>::uniform{0, static_cast<int>(s)};
auto r = std::vector<fraction>(s, 0);
for( auto& i: r ) {
i.setNumerator(u(e1));
i.setDenominator(u(e1));
}
return r;
}
template <typename T> Collection {
private:
// this will handle all your memory management needs
std::vector<T> randoms;
public:
Collection(size_t s) :
randoms{createRandomNumbers<T>(s)}
{};
createNewRandoms(size_t s) {
std::swap(randoms, createRandomNumbers<T>(s));
};
// whatever else is necessary
};