moo
moo

Reputation: 526

Variadic template constructor and empty constructor?

I have a class like the following:

template<typename ... TTypes>
class Composite {
public:
    //Composite() : null(true) { } 
    Composite(TTypes... values) : values(std::make_tuple(values...)), null(false) { }
private:
    bool null;
    std::tuple<TTypes...> values;
};

int main(int argc, char *argv[]) {
    Composite<int, char, int> a1;
}

But this leads to an error because the second constructor would override the first one with TTypes = {}. Is there any way to keep the empty constructor?

Best, Moritz

Upvotes: 4

Views: 1540

Answers (3)

SteakOverflow
SteakOverflow

Reputation: 2033

Since none of the existing answers so actually solve the problem, but there is a solution by Piotr Skotnicki hidden in the comments, I'm just gonna repost it here for visibility:

#include <tuple>
#include <type_traits>

template<typename ... TTypes>
class Composite {
public:
    Composite() : null(true) { } 

    template <std::size_t N = sizeof...(TTypes), typename std::enable_if<(N>0), int>::type = 0>
    Composite(TTypes... values) : values(std::make_tuple(values...)), null(false) { }
private:
    bool null;
    std::tuple<TTypes...> values;
};

int main(int argc, char *argv[]) {
    Composite<int, char, int> a1;
    Composite<> a2;
}

Upvotes: 4

Jorge Bellon
Jorge Bellon

Reputation: 3096

The case where your parameter pack TTypes is empty makes the default constructor ambiguous. If you plan to provide at least 1 parameter, then you can specify an additional parameter:

template<typename TType, typename ... TTypes>
class Composite {
public:
    Composite() : null(true) { } 
    Composite(TType first, TTypes... rest) :
      values(std::make_tuple(first,rest...)),
      null(false)
    {
    }
private:
    bool null;
    std::tuple<TType,TTypes...> values;
};

int main(int argc, char *argv[]) {
    Composite<int, char, int> a1;
}

However, take into account that this functionality is provided by std::optional, so it should be better using it.

template < typename... TTypes >
using Composite = std::optional<std::tuple<TTypes...>>;

Upvotes: 0

R Sahu
R Sahu

Reputation: 206577

I am not sure whether the following work around is an option for you:

template<typename ... TTypes>
class Composite : public ValueSet {
public:
    Composite(TTypes... values) { }
};

template<>
class Composite<> : public ValueSet {
public:
    Composite() : ValueSet() { } 
};

but it works.

Upvotes: 0

Related Questions