Search code examples
c++templatesvariadic-templatestype-traitsparameter-pack

Const-qualifier lost on variadic template parameter when trying to pretty-print function signature


I wish to use template programming with type traits to pretty-print the signature of a function. While the gist of what I came up with works, the const-qualifier on the function arguments is dropped. Where do I lose the qualifier and what can I do to prevent this?

#include <iostream>
#include <type_traits>

template <typename T>
void print_type_info() {
    if (std::is_const_v<T>) {
        std::cout << "const ";
    }
    std::cout << typeid(T).name() << std::endl;
}

template <typename... Args>
void print_function_args() {
    (print_type_info<Args>(), ...);
}

template <typename Ret, typename... Args>
void print_function_signature(Ret(*)(Args...)) {
    print_function_args<Args...>();
}

void my_function(int, const int) {}

int main() {
    print_function_signature(my_function); // not ok: print 'i' for both arguments
    print_function_args<const int>(); // ok, prints 'const i'
    return 0;
}

Solution

  • Welcome to legacy features.

    const A(int [7]) and similar function signatures are a lie. C++ drops top level const and top level array sizes and the like from the actual signature.

    In the body you can declare them const and get it enforced internally, but void foo(int) and void foo(int const) are the same overload as far as C++ is concerned.

    This is one of the reasons why std::result_of was rewritten; the types get converted everywhere.