Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;如何在泛型编程中声明自定义数组_C++_Templates_Generic Programming - Fatal编程技术网

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
};