Search code examples
c++templatesinitialization-list

Default constructor in template class with attribute of unknown type


I need a default constructor with no argument. How can I initialize attribute a which is of unknown type to me.

template <typename Type>
class Foo
{
public:
    Foo() : a(), b(0) {}  <---- Here is the confusion

private:
    Type a;
    int b;
};

Edit : Answer has been given in comments below, but there is still something I don't understand. If I have :

typedef enum {AB, CD} EnumType

template <typename Type>
class Foo
{
public:
    Foo() {}  // <---- "Member 'b' was no initialized in this constructor"

private:
    Type a;
    EnumType b;
};

my compiler gives me this warning : Member 'b' was no initialized in this constructor. Why is it giving me this warning for b which is an enum and not for a ?


Solution

  • this is correct as long as type Type has default constructor. when you declare template you are assuming some things about types, not every type can be passed in constructor of specific template. here, everything will be just fine for standard types and for those that have default constructor. if you initialize class Foo with your own type that doesn't provide default constructor it will be an error.

    to answer your second issue:

    If you had defined your variable at namespace scope, it would be value initialized to 0.

    enum SomeEnum {  
        EValue1 = 1,  
        EValue2 = 4,  
    };
    SomeEnum e; // e is 0
    int i;      // i is 0
    
    int main()
    {
        cout << e << " " << i; //prints 0 0 
    }
    

    Don't be surprised that e can have values different from any of SomeEnum's enumerator values. Each enumeration type has an underlying integral type(such as int, short, or long) and the set of possible values of an object of that enumeration type is the set of values that the underlying integral type has. Enum is just a way to conveniently name some of the values and create a new type, but you don't restrict the values of your enumeration by the set of the enumerators' values.

    To zero-initialize an object of type T means:
    — if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;

    Note that enumerations are scalar types.

    To value-initialize an object of type T means:
    — if T is a class type blah blah
    — if T is a non-union class type blah blah
    — if T is an array type, then blah blah — otherwise, the object is zero-initialized

    typedef enum {a,b,c,d} EnumType;
    
    template <typename Type>
    class Foo
    {
    public:
        Foo() {}  // <---- "Member 'b' was no initialized in this constructor"
    
    public:
        Type a;
        EnumType b;
    };
    
    /*
     * 
     */
    int main(int argc, char** argv) {
    
        Foo<int> fo;
        std::cout<<std::endl<<"fo.a:"<<fo.a<<",fo.b:"<<fo.b<<std::endl;
        EnumType e=d;
        fo.b=d;
        std::cout<<std::endl<<"fo.a:"<<fo.a<<",fo.b:"<<fo.b<<std::endl;
    
        Foo<int>* go=new Foo<int>;
        std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl;
        go->b=d;
        std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl;
    

    fo.a:-137090040,fo.b:32767

    fo.a:-137090040,fo.b:3

    go->a:-166889576,go->b:32767

    go->a:-166889576,go->b:3

    now:

        Foo<int>* go=new Foo<int>();
        std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl;
        go->b=d;
        std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl;
    

    go->a:0,go->b:0

    go->a:0,go->b:3