Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template functions: default construction without copy-constructing in C++

Considering

struct C { 
   C()            { printf("C::C()\n"          ); }
   C(int)         { printf("C::C(int)\n"       ); }
   C( const C& )  { printf("copy-constructed\n"); }
};

And a template function

template< typename T > void foo(){
    // default-construct a temporary variable of type T
    // this is what the question is about.
    T t1;       // will be uninitialized for e.g. int, float, ...
    T t2 = T(); // will call default constructor, then copy constructor... :(
    T t3();     // deception: this is a local function declaration :(
}

int main(){
    foo<int>();
    foo<C  >();
}

Looking at t1, it will not be initialized when T is e.g. int. On the other hand, t2 will be copy-constructed from a default constructed temporary.

The question: is it possible in C++ to default-construct a generic variable, other than with template-fu?

like image 542
xtofl Avatar asked Mar 14 '11 18:03

xtofl


2 Answers

Here's a trick you can use, using a local class:

template <typename T> void foo() {
    struct THolder {
        T obj;
        THolder() : obj() { } // value-initialize obj
    };

    THolder t1; // t1.obj is value-initialized
}

I think I read about this trick from an answer to another Stack Overflow question, but I am unable to find that question at the moment.

Alternatively, you can use the boost::value_initialized<T> class template, which basically does the same thing, with greater flexibility and consistency and with workarounds for buggy compilers.

In C++0x, it's much easier: you can use an empty initializer list:

T obj{}; // obj is value-initialized

(To the best of my knowledge, only gcc 4.5+ supports C++0x initializer lists. Clang and Visual C++ don't yet support them.)

like image 59
James McNellis Avatar answered Sep 28 '22 03:09

James McNellis


If you don’t care for the fact that the copy constructor must exist, and just want to prevent it being called:

Don’t worry: it won’t be. The copy constructor call will be elided in this situation. Always, and reliably – even when you compile with optimizations disabled (-O0).

like image 26
Konrad Rudolph Avatar answered Sep 28 '22 03:09

Konrad Rudolph