How do I stop this templated function value-initializing a new constructed object?

34 views Asked by At

If I can a parameter pack for the constructor arguments when I create a new object and I don't provide any constructor arguments then the result will be: new T(); which will value-initialize the object if it doesn't have a user-provided constructor. How do I stop this from happening?

template <typename T>
struct Foo
{
    template <typename ... ConstructorArgs>
    static void create(ConstructorArgs ... constructorArgs)
    {
        T* ptr = new T(constructorArgs ...);
        T* ptr2 = new T;
        std::cout << *ptr; // It seems it value-initialized (zero-initialized) it
        std::cout << *ptr2; // Default initialized it

    }

};
int main()
{
    Foo<int>::create();
}
1

There are 1 answers

1
Zebrafish On

This is working with constexpr sizeof... (ConstructorArgs), but I'd also like to know if there's a better way.

template <typename T>
struct Foo
{
    template <typename ... ConstructorArgs>
    static void create(ConstructorArgs ... constructorArgs)
    {
        T* ptr;
        if constexpr (sizeof ... (ConstructorArgs) == 0)
            ptr = new T;
        else
            ptr = new T(constructorArgs ...);
    }

};
int main()
{
    Foo<int>::create(); // Default initializes
    Foo<int>::create(0); // Value/Zero initialized

}

It works with new and placement new, and with a lvalue stack variable, but not a temporary, ie., T{ }, as those braces will value-initialize if T has no user-defined constructor.