Home > Enterprise >  Passing parameter pack in constexpr
Passing parameter pack in constexpr

Time:05-24

i am trying to determine the size of all passed objects at compile time and then abort the build process via static_assert when a maximum size is exceeded.

#include <iostream>

template<class T>
class Test
{
public:
    T value;
    constexpr size_t size() const { return sizeof(T)   3; }
};

template<typename ...T>
constexpr int calc(const T&...args)
{
    return (args.size()   ...);
}

template<typename ...T>
void wrapper(const T& ...args)
{
    // error: 'args#0' is not a constant expression
    constexpr int v = calc(args...);
    static_assert(v <= 11, "oops"); 
}

int main()
{
    Test<int> a;
    Test<char> b;
    // a.size()   b.size() == 11

    // works
    constexpr int v = calc(a, b);
    static_assert(v <= 11, "oops"); 

    // wrapper function
    wrapper(a, b);  
}

run on godbolt

it works perfectly if i call the calculation function directly with the objects. but if i use a wrapper function and pass the parameter pack, suddenly the parameters don't seem to be constant anymore. does anyone know how i can fix this problem?

CodePudding user response:

Function arguments are not constexpr expressions (for good reasons) even if part of constexpr or consteval functions.

If you are willing to make Test::size static, independent of objects:

#include <iostream>

template<class T>
class Test
{
public:
    T value;
    constexpr static size_t size() { return sizeof(T)   3; }
};

template<typename ...T>
constexpr size_t calc_types()
{
    return (T::size()   ...);
}

template<typename ...T>
constexpr size_t calc_vals(const T&...)
{
    return calc_types<T...>();
}


template<typename ...T>
constexpr void wrapper_types()
{
    static_assert(calc_types<T...>() <= 11, "oops"); 
}

template<typename ...T>
constexpr void wrapper_vals(const T&...)
{
    wrapper_types<T...>();    
}


int main()
{
    Test<int> a;
    Test<char> b;
    // a.size()   b.size() == 11

    // works
    constexpr int v = calc_vals(a, b);
    static_assert(v <= 11, "oops"); 

    // wrapper function
    wrapper_vals(a, b);  
}
  • Related