I'm playing around with std::source_location
as a means to define a static identifier for a class which behaves similar to a compile-time counter. The basic idea is rather simple: use a class template taking an integral_constant
as template parameter and at the site of instantiation pass the constant expression std::source_location::current().line()
to the class.
With the following code using a macro, I can get this behavior without explicitly spelling the std::source_location
:
#include <iostream>
#include <source_location>
template<typename, typename index>
struct A_impl
{
static constexpr auto line() { return index::value; }
};
template<template<typename ...> typename temp, typename index>
struct line_manager
{
template<typename ... Ts>
using type = temp<Ts ..., index>;
};
#define A typename line_manager<A_impl, std::integral_constant<int, std::source_location::current().line()> >::type
This can be used as in the following code and allows to separate the two object instantiations at compile time:
int main()
{
A<double> a; //expands to A_impl<double, integral_constant<int, line()> >
A<double> b;
if constexpr(a.line() != b.line())
{
std::cout<<a.line()<<std::endl;
std::cout<<b.line()<<std::endl;
}
}
Can the same behavior as in the code above -- i.e. logging the source line as a constant expression without explicitly specifying it in the instantiation -- can also be obtained without a macro?
Side note: I know that the above code is not functional, as you could also write A<double> a,b
and obtain the same line. That doesn't matter here.