Search code examples
c++variadic-functions

C++ Multiple function parameters with varargs of a specific type


I am relatively new to C++ coming from a Java background so I am not sure if the functionality I am looking for is directly possible.

I am attempting to create a C++ function that accepts two different parameters but with the following requirements: The first parameter is a single input object of a specific type and the second parameter is a variable list of additional objects all of the which are the same type as the first parameter.

I am specifically looking for something similar to this Java code (if possible).

public static <E> boolean func(E input, E... args) {}

If this is not possible, does anyone know of some sort of implementation to make this to work for strings specifically? Something along the lines of:

bool func(std::string input, std::string... args) {}

I have researched this topic a bit and found that function templates might be able to help here, but I am unsure on how to support multiple parameter types (of the same datatype) using this approach.

My initial line of thinking was to try something like this:

template<class... T>
bool func(const T input, const T&... args) {}

But this only accounts for the varargs parameter type, not the first parameter.

Any help/advice is greatly appreciated. Thanks in advance.


Solution

  • You need to define two templates types, one for the input and one for the parameter pack.

    The function would then look like this:

    template <typename T, typename ... Ts>
    bool func(const T & input, const Ts & ... args);
    

    To guarantee all the types are the same, we can combine std::conjunction with std::is_same.

    We can also make use of static_assert so that we can generate an error at compile time if the condition is not satisfied.
    It allows us to provide a custom error message so that the error would be clearer and easier for the user to understand.

    It would then become:

    template <typename T, typename ... Ts>
    bool func(const T & input, const Ts & ... args)
    {
        static_assert(std::conjunction_v<std::is_same<T, Ts>...>, "Error: All parameters must be of the same type.");
    
        //...
    
        return true;
    }
    

    You could also use std::enable_if instead of static_assert.

    I personally prefer to use static_assert because we can make the error more explicit. If we use std::enable_if, in case of failure, the user will still need to check on his/her own what was the evaluated condition to find out what was wrong.

    In that case, the function would be like:

    template <typename T, typename ... Ts>
    std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>, bool>
    func(const T & input, const Ts & ... args)
    {
        //...
    
        return true;
    }