Search code examples
c++c++11templatesinitializationc++17

How to Ensure proper initialization of Non Static Data Members within a Class Template in C++


I am working with templates in C++ and want to know how can we properly(value) initialize the non static data members in a class template. For example, consider the following snippet:

template<typename T>
class MyVector
{
    T x; // x has undefined value for a built in type
};

Now i know that the data member x has garbage value for built in types in local/block scope unless explicitly initialized.

So i want to value initialize the data member. If i modify the above code to:

template<typename T>
class MyVector
{
    T x(); // now x becomes a member function 
};

As can be seen in the above modified code snippet, x is now a member function. How can i value initialize the data member x for type T?


Solution

  • There are different way to do what you want depending upon which C++ version you're using. This is explained in more detail below:

    C++11

    template<typename T>
    class MyVector
    {
        T x{}; 
    };
    

    Pre C++11

    template<typename T>
    class MyVector
    {
        T x;
        MyVector(): x()
        {
        }
    };
    

    C++11

    From C++11 and onwards, you can also write(using constructor initializer list):

    template<typename T>
    class MyVector
    {
        T x;
        MyVector(): x{}
        {
        }
    };
    

    C++11

    Note that this version won't work if the constructor for copy initialization is explicit since there is no mandatory copy elision.

    #include <iostream>
    
    using namespace std;
    struct Name 
    {
        explicit Name(const Name&)
      {
          
      }
      Name() = default;
    };
    template<typename T>
    class MyVector
    {
        public:
        T x = T();
        
    };
    int main()
    {
        cout<<"Hello World";
        MyVector<int> p; // works with C++11,C++17 etc
        MyVector<Name> n; //error with C++11 and C++14
        return 0;
    }
    
    

    But the above version will work with C++17 since there is mandatory copy elision in C++17.

    #include <iostream>
    
    using namespace std;
    struct Name 
    {
        explicit Name(const Name&)
      {
          
      }
      Name() = default;
    };
    template<typename T>
    class MyVector
    {
        public:
        T x = T();
        
    };
    int main()
    {
        cout<<"Hello World";
        MyVector<int> p; // works with C++11,C++17 and following
        MyVector<Name> n; //works with C++17 due to mandatory copy elision
        return 0;
    }