Reputation: 2100
I have to use a macro PERF_INSTRUMENT
from a library. PERF_INSTRUMENT
expects a user provided c-style string as a function name to print the location of this instrument point.
But, I don't want to write the function name everytime I use PERF_INSTRUMENT
instead I want to call it with __func__
so that function name is automatically included in the perf log.
But when I use __func__
it actually returns operator()
because the __func__
is embedded inside the lambda function.
Is their any way by which I can pass the main()
function name to the PERF_INSTRUMENT
macro.
#include <cstdio>
#include <cassert>
#include <type_traits>
using namespace std;
namespace /* anonymous */
{
template< typename T >
struct Is_Const_Char_Array
: std::is_same< std::remove_reference_t< T >,
char const[ std::extent< std::remove_reference_t< T > >::value ] >
{};
template< typename T >
struct Is_C_String_Literal
: Is_Const_Char_Array< T >
{};
}
#define PERF_INSTRUMENT(name) auto instObj = [] { static_assert( Is_C_String_Literal< decltype( name ) >::value, "input argument must be a c-string literal" ); /* Some other Logic*/ printf(name);return 1; }()
// <------------------ MY CODE -------------------> //
int main(){
PERF_INSTRUMENT("main"); // <-- this works fine
PERF_INSTRUMENT(__func__); // <-- this prints operator()
// PERF_INSTRUMENT(__builtin_FUNCTION());
}
Please Note that I can only change the code below the MY CODE line
Upvotes: 3
Views: 1307
Reputation: 66190
Is their any way by which I can pass the main function name to the PERF_INSTRUMENT macro.
You can pass "name
" as argument to the lambda itself.
Something as
#define PERF_INSTRUMENT(name) \
auto instObj = [](char const * str) \ // <-- receive an argument
{ static_assert( Is_C_String_Literal< decltype( name ) >::value, \
"input argument must be a c-string literal" );\
/* Some other Logic*/ \
printf(str); \ // <-- print the argument received, not directly name
return 1;\
}(name)
//.......^^^^ pass name as argument
Bonus Off Topic proposal: to detect is an object is a C-string literal, i propose an alternative way
template <typename T>
constexpr std::false_type islHelper (T, long);
template <typename T, std::size_t N>
constexpr std::true_type islHelper (T const(&)[N], int);
template <typename T>
using isStringLiteral = decltype(islHelper(std::declval<T>(), 0));
In static_assert()
become
static_assert( isStringLiteral<decltype(name)>::value,
"input argument must be a c-string literal" );
Upvotes: 5
Reputation: 66371
Since the assert is fundamentally flawed – it accepts any const
char array – wrapping the macro in another macro should work.
Something like this:
#define PERF_FUNCTION do { \
const char name[] = __func__; \
PERF_INSTRUMENT(name); \
} while(0)
Upvotes: 0