c++ variadic-templates c++20 default-arguments std-source-location

c++ - ¿Cómo usar source_location en una función de plantilla variadic?



variadic-templates c++20 (4)

No es una gran solución, pero ... ¿qué hay de colocar los argumentos variables en una std::tuple ?

Quiero decir ... algo como

template <typename... Args> void debug (std::tuple<Args...> && t_args, std::source_location const & loc = std::source_location::current());

Desafortunadamente, de esta manera tienes que llamar explícitamente a std::make_tuple llamándolo

debug(std::make_tuple(1, 2l, 3ll));

La característica C ++ 20 std::source_location se usa para capturar información sobre el contexto en el que se llama a una función. Cuando trato de usarlo con una función de plantilla variadic, encontré un problema: no puedo ver un lugar para colocar el parámetro source_location .

Lo siguiente no funciona porque los parámetros variables deben estar al final:

// doesn''t work template <typename... Args> void debug(Args&&... args, const std::source_location& loc = std::source_location::current());

Lo siguiente tampoco funciona porque la persona que llama se arruinará por el parámetro insertado en el medio:

// doesn''t work either, because ... template <typename... Args> void debug(const std::source_location& loc = std::source_location::current(), Args&&... args); // the caller will get confused debug(42); // error: cannot convert 42 to std::source_location

Me informaron en un comment que std::source_location funciona a la perfección con plantillas variadas, pero me cuesta entender cómo. ¿Cómo puedo usar std::source_location source_location con funciones de plantilla variadic?


Simplemente ponga sus argumentos en una tupla, no se necesita macro.

#include <source_location> #include <tuple> template <typename... Args> void debug( std::tuple<Args...> args, const std::source_location& loc = std::source_location::current()) { std::cout << "debug() called from source location " << loc.file_name() << ":" << loc.line() << ''/n''; }

Y esto works * .

Técnicamente podrías escribir:

template <typename T> void debug( T arg, const std::source_location& loc = std::source_location::current()) { std::cout << "debug() called from source location " << loc.file_name() << ":" << loc.line() << ''/n''; }

pero entonces probablemente tendrías que saltar algunos aros para obtener los tipos de argumento.

* En el ejemplo vinculado, estoy usando <experimental/source_location> porque eso es lo que los compiladores aceptan en este momento. Además, agregué un código para imprimir la tupla de argumento.


template <typename... Args> void debug(Args&&... args, const std::source_location& loc = std::source_location::current());

"funciona", pero requiere especificar argumentos de plantilla ya que no son deducibles ya que no son los últimos:

debug<int>(42);

Demo

Las posibles alternativas (no perfectas) incluyen:

  • use sobrecargas con límite codificado (antigua forma posible de "manejar" la variadic):

    // 0 arguments void debug(const std::source_location& loc = std::source_location::current()); // 1 argument template <typename T0> void debug(T0&& t0, const std::source_location& loc = std::source_location::current()); // 2 arguments template <typename T0, typename T1> void debug(T0&& t0, T1&& t1, const std::source_location& loc = std::source_location::current()); // ...

    Demo

  • para poner source_location en la primera posición, sin valor predeterminado:

    template <typename... Args> void debug(const std::source_location& loc, Args&&... args);

    y

    debug(std::source_location::current(), 42);

    Demo

  • de manera similar a las sobrecargas, pero solo use tupla como grupo

    template <typename Tuple> void debug(Tuple&& t, const std::source_location& loc = std::source_location::current());

    o

    template <typename ... Ts> void debug(const std::tuple<Ts...>& t, const std::source_location& loc = std::source_location::current());

    con uso

    debug(std::make_tuple(42));

    Demo


template <typename... Ts> struct debug { debug(Ts&&... ts, const std::source_location& loc = std::source_location::current()); }; template <typename... Ts> debug(Ts&&...) -> debug<Ts...>;

Prueba:

int main() { debug(5, ''A'', 3.14f, "foo"); }

DEMO