LordFinn
LordFinn

Reputation: 23

How to call a copy constructor only if it exist ? c++

I'm making an Entity-Component-System Engine and I have a little trouble with prefabs. I want to copy a prefab, only if the class that the user pass has template is copy constructible. A simple implementation of what I want to do will be something like that :

void addFromPrefab() { //We assume that _prefab is of type std::shared_ptr<T>
    if (std::is_copy_constructible<T>::value)
        addComponent(*_prefab); // Add a new component by copy constructing the prefab passed as parameter
    else if (std::is_default_constructible<T>::value)
        addComponent(); // Add a new component with his default constructor
    else
        throw std::exception();
}

template<typename ...Args>
void addComponent(Args &&...args) {
    store.emplace_back(std::make_shared<T>(args ...));
}

Is there a way to make this code working? Actually, it throws me that it can't create a specific class because it's a copy-constructible constructor is deleted (Which is the case).

Thanks in advance, and sorry for my mistakes I'm french ;)

Upvotes: 2

Views: 83

Answers (1)

Matthieu Brucher
Matthieu Brucher

Reputation: 22023

If you have C++17, use if constexpr:

void addFromPrefab() { //We assume that _prefab is of type std::shared_ptr<T>
    if constexpr(std::is_copy_constructible<T>::value)
        addComponent(*_prefab); // Add a new component by copy constructing the prefab passed as parameter
    else if constexpr(std::is_default_constructible<T>::value)
        addComponent(); // Add a new component with his default constructor
    else
        throw std::exception();
}

If you don't, you have to use SFINAE:

std::enable_if<std::is_copy_constructible<T>::value> addFromPrefab() { //We assume that _prefab is of type std::shared_ptr<T>
    addComponent(*_prefab); // Add a new component by copy constructing the prefab passed as parameter
}
std::enable_if<!std::is_copy_constructible<T>::value && std::is_default_constructible<T>::value> addFromPrefab() {
    addComponent(); // Add a new component with his default constructor
}

std::enable_if<!std::is_copy_constructible<T>::value && !std::is_default_constructible<T>::value> addFromPrefab() {
        throw std::exception();
}

Upvotes: 3

Related Questions