Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++_Templates_Constructor - Fatal编程技术网

C++ 初始化嵌套模板

C++ 初始化嵌套模板,c++,templates,constructor,C++,Templates,Constructor,我正在努力学习更多关于模板的知识,但遇到了一个似乎无法解决的问题。目前,下面的班级运转良好 #include <iostream> #include <vector> #include <cstring> using namespace std; template <class T, int s> class myArray{ public: T* data; inline T& operator[](const int

我正在努力学习更多关于模板的知识,但遇到了一个似乎无法解决的问题。目前,下面的班级运转良好

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

template <class T, int s>
class myArray{
public:
    T* data;
    inline T& operator[](const int i){return data[i];}
    myArray(){
        data=new T[s];
    }
    myArray(const myArray& other){
        data=new T[s];
        copy(other.data,other.data+s,data);
    }
    myArray& operator=(const myArray& other){
        data=new T[s];
        copy(other.data,other.data+s,data);
        return *this;
    }
    ~myArray(){delete [] data;}
};  

我认为当数据不是int类型(即维度大于1的任何数组上)时,这应该失败,但是它不是。当数组为正方形时,它会工作,但如果不是,则某些条目不会设置为10。有人知道标准向量类是如何实现这一点的吗?任何帮助都将是惊人的。谢谢

好吧,试试这样:

 myArray()
 : data(new T[s]())      // value-initialization!
 {
 }

 myArray(T const & val)
 : data(new T[s])        // default-initialization suffices
 {
     std::fill(data, data + s, val);
 }
如果你对可变模板感兴趣,你可能会编造一些更奇怪的涉及可变填充初始值设定项列表的东西,但我认为我们已经做了足够一周的学习


请注意使用
new
的基本缺陷:任何一个版本都要求类
T
可以在某种“默认”状态下实例化,并且它是可赋值的,即使我们在第二个版本中从未要求默认状态。这就是为什么“真实”库将内存分配和对象构造分开,并且除非是放置版本,否则您永远不会看到新的表达式。

std::vector在内存块上使用新的放置。在第二行代码中分配内存后,它构造数据

这项技术也适用于您。注意放置新的位置,因为它也需要手动调用析构函数

这是一条半途而废的路线,没有新的布局:

template<typename U>
explicit MyArray( U const& constructFromAnythingElse )
{
  AllocateSpace(N); // write this, just allocates space
  for (int i = 0; i < N; ++i)
  {
    Element(i) = T( constructFromAnythingElse );
  }
}
模板
显式MyArray(U const&constructFromAnythingElse)
{
AllocateSpace(N);//写这个,只分配空间
对于(int i=0;i
使用placement new,您必须首先分配内存,然后就地构造,然后记住在最后销毁每个元素

与放置新路由相比,上面的方法是半途而废的,因为我们首先构建每个元素,然后构建另一个元素,并使用
operator=
覆盖它

通过使其成为任意类型上的模板构造函数,我们不需要依靠多次转换将多个级别下放到数组中。朴素的版本(取T常量&)不起作用,因为要构造一个由T数组组成的数组,最外层的版本需要一个由T数组组成的数组作为参数,而最外层的版本需要一个由T数组组成的数组作为参数,最外层的版本需要一个由T数组组成的数组作为参数,而最外层的版本需要一个由T组成的数组——用户定义的构造层次太多了


使用上述模板构造函数,数组的数组接受任何类型作为构造函数。正如T数组一样,T数组也是如此。最后,T被传递到构建T数组最外层数组的任何地方,如果它不喜欢,就会得到一条几乎完全无法读取的编译器错误消息。

对包含其他数组的数组进行专门化。要做到这一点,您需要在通用和专用MyArray中使用一些常见的实现类:

常见实现(我为您做了一些修复-请参见!!!注释):

以及myArray的myArray专用版本-另请参见
value\u type
setAll
中的差异:

template <class T, int s1, int s2>
class myArray<myArray<T,s2>,s1> : private myArrayImpl<myArray<T,s2>,s1> {
    typedef myArrayImpl<myArray<T,s2>,s1> Impl;
public:
    using Impl::operator[];
    myArray() : Impl() {}
    typedef typename myArray<T,s2>::value_type value_type; // !!!
    explicit myArray(const value_type& value) {
       setAll(value);
    }
    void setAll(const value_type& value) {
       for_each(this->data, this->data + s1, [value](myArray<T,s2>& v) { v.setAll(value); });
    }
};  
模板
类myArray:private myArrayImpl{
typedef myArrayImpl Impl;
公众:
使用Impl::operator[];
myArray():Impl(){}
typedef typename myArray::value\u type value\u type;/!!!
显式myArray(常量值\类型和值){
setAll(值);
}
void setAll(常量值\类型和值){
对于每个(this->data,this->data+s1,[value](myArray&v){v.setAll(value);});
}
};  
使用方法:

int main() {
  myArray<myArray<myArray<int,7>,8>,9> a(7);
  std::cout << a[0][0][0] << std::endl;
  std::cout << a[8][7][6] << std::endl;
}
intmain(){
mya阵列(7);

std::cout您的赋值运算符没有清除旧数据。谢谢。我这样做了,并且在“myArray”具有2个或更少维度时它会工作。对于更大的数组,我会得到“调用“myArray::myArray(int)”时没有匹配的函数”。如果有人有机会看一眼,这是我的新代码:谢谢!为什么不使用模板显式myArray(U const&U)?也就是说,接受任何类型,如果它不能用于构建内容,就会得到一个错误。实际上,我们想说的是“任何可以用于构建我的内容的东西对我来说都是公平的游戏”--如果您的内容是myArrays,您的工作正常。@Yakk您可能是对的-我没有检查-但这似乎是合理的…我只是担心它太笼统了。此外,我的解决方案中可以使用任何可转换为值的类型\u type-并且此转换只会执行一次-不是针对[multi]中的每个单元格阵列。这是您的解决方案的一个很好的功能!+1
template<typename U>
explicit MyArray( U const& constructFromAnythingElse )
{
  AllocateSpace(N); // write this, just allocates space
  for (int i = 0; i < N; ++i)
  {
    Element(i) = T( constructFromAnythingElse );
  }
}
template <class T, int s>
class myArrayImpl {
public:
    T* data;
    T& operator[](int i){return data[i];} //!!! const before int not needed
    const T& operator[](int i) const {return data[i];} //!!! was missing
    myArrayImpl(){
        data=new T[s]();
    }
    myArrayImpl(const myArrayImpl & other){
        data=new T[s];
        copy(other.data,other.data+s,data);
    }
    myArrayImpl& operator=(const myArrayImpl& other){
        T* olddata = data; // !!! need to store old data
        data=new T[s];
        copy(other.data,other.data+s,data);
        delete [] olddata; //!!! to delete it after copying
        return *this;
    }
    ~myArrayImpl(){delete [] data;}
};  
template <class T, int s>
class myArray : private myArrayImpl<T,s> {
    typedef myArrayImpl<T,s> Impl;
public:
    using Impl::operator[];
    myArray() : Impl() {}
    typedef T value_type; // !!!
    explicit myArray(const value_type& value) {
       setAll(value);
    }
    void setAll(const value_type& value) {
       fill(this->data, this->data + s, value);
    }
};
template <class T, int s1, int s2>
class myArray<myArray<T,s2>,s1> : private myArrayImpl<myArray<T,s2>,s1> {
    typedef myArrayImpl<myArray<T,s2>,s1> Impl;
public:
    using Impl::operator[];
    myArray() : Impl() {}
    typedef typename myArray<T,s2>::value_type value_type; // !!!
    explicit myArray(const value_type& value) {
       setAll(value);
    }
    void setAll(const value_type& value) {
       for_each(this->data, this->data + s1, [value](myArray<T,s2>& v) { v.setAll(value); });
    }
};  
int main() {
  myArray<myArray<myArray<int,7>,8>,9> a(7);
  std::cout << a[0][0][0] << std::endl;
  std::cout << a[8][7][6] << std::endl;
}