Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we use int... as an argument for template parameter pack directly?

Here is my problem:

template <class... Ts>
struct iniClass
{
private:
    std::initializer_list<int> m_data;
    int x;

public:
    iniClass(Ts... vars)
        : m_data({vars...}), x(8)
    {
        std::cout << "created object with first constructor\n";
        prin();
    }
    void prin()
    {
        for (auto var : m_data)
        {
            std::cout << var << ", ";
        }
        std::cout << '\n';
    }
};

int main()
{
    iniClass<std::initializer_list<int>> il1({1, 2, 3, 4}); // Work like a charm!
    iniClass<int...> il2(1, 2, 3, 4);                       // Didn't work, How to make this work?
}

Can we use int... (,and generally primativeTYPE...) as an argument for template parameter pack directly?
Is there a way to make it work in that way?

like image 304
Rango Avatar asked Dec 15 '25 07:12

Rango


1 Answers

No, this feature is currently not part of the C++ standard. The closest thing we have is:

// P1219 proposed syntax
void foo(int... args);

// C++20
void foo(std::convertible_to<int> auto&&... args);

// C++17
template <typename... Ts>
auto foo(Ts&&... args)
  -> std::enable_if_t<(std::is_convertible_v<Ts, int> && ...)>;

// C++14
template <typename... Ts>
auto foo(Ts&&... args)
  -> std::enable_if_t<CONJUNCTION<std::is_convertible<Ts, int>...>::value>;
// TODO: implement a conjunction trait like std::conjunction

// C++11
template <typename... Ts>
auto foo(Ts&&... args)
  -> typename std::enable_if<CONJUNCTION<std::is_convertible<Ts, int>...>::value>::type;

There is a well-received proposal which adds this feature though. See P1219 - Homogeneous variadic function parameters. This proposal has been rejected for C++23 by EWG (Evolution Working Group), however, it is possible that a revised version could make it into a future standard.

It doesn't really look like you need this feature though. You could just use std::array, which does support construction like:

// std::make_array, (from library fundamentals TS v2) (C++26?)
// you could implement this yourself in C++11
auto arr = std::experimental::make_array<int>(1, 2, 3, 4, 5);

// std::to_array, since C++20
// you could implement this yourself in C++11
auto arr = std::to_array<int>({1, 2, 3, 4, 5});

// CTAD, since C++17
std::array arr{1, 2, 3, 4, 5};

// C++11, works out of the box
std::array<int, 5> arr{1, 2, 3, 4, 5};

// C-style arrays
int arr[] {1, 2, 3, 4, 5};

Your iniClass is basically an array anyway. Also, it's a bad idea to ever store std::initializer_list, because it doesn't own its contents. It's like a pointer or reference.

like image 169
Jan Schultke Avatar answered Dec 16 '25 22:12

Jan Schultke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!