Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template function with multiple parameters of same type

I'm trying to create a function that can take multiple parameters of the same type, passed in as a template. The number of arguments is known in compile time:

struct Foo
{
    int a, b, c;
};

template <uint32_t argsCount, typename T>
void fun(T ...args) // max number of args == argsCount
{
    // ...
    // std::array<T, argsCount>{ args... };
}

int main()
{
    fun<3, Foo>( { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } );

    // Dont want to do:
    // fun( Foo{}, Foo{}, Foo{} );
    // nor:
    // fun<Foo, Foo, Foo>( ... );

    return 0;
}

I must take into consideration these constraints:

  • no heap memory allocations
  • no va_args

Is it possible to do something similar in C++14 (preferably C++14, but curious what are the solutions in newer versions)?

edit: cleaned up the initial sloppy pseudcode.

like image 635
wjan Avatar asked May 08 '26 20:05

wjan


2 Answers

With a slightly different syntax on the call site, you could do it by taking a reference to an array:

template<typename T, std::size_t N>
void fun(const T(& args)[N]) {
    auto args_as_stdarray = std::to_array(args);
}

fun<Foo>({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
like image 194
Evg Avatar answered May 11 '26 11:05

Evg


If you change the function into a functor, you can introduce a parameter pack in the body of the type of the functor.

First create a helper to turn <N, T> -> std::tuple<T, T, T, ..., T> (N times):

template<std::size_t N, typename T>
struct repeat {
private:
    // enable_if<true, T> == type_identity<T>
    template<std::size_t... I>
    static std::enable_if<true, std::tuple<std::enable_if_t<I==I, T>...>>
    get(std::index_sequence<I...>);
public:
    using type = typename decltype(get(std::make_index_sequence<N>{}))::type;
};

Then have your functor take a std::tuple<Args...>, where Args will be a parameter pack with T N times:

template<typename T, typename Args>
struct fun_t;

template<typename T, typename... Args>
struct fun_t<T, std::tuple<Args...>> {
    static constexpr std::size_t argsCount = sizeof...(Args);

    void operator()(Args... args) const {
        // ...
        // std::array<T, argsCount>{ args... };
    }
};

template<std::uint32_t argCount, typename T>
constexpr fun_t<T, typename repeat<argCount, T>::type> fun;


int main() {
    fun<3, Foo>({ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 });
}
like image 30
Artyer Avatar answered May 11 '26 11:05

Artyer



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!