Print macro values without knowing the amount of macros - c++

I have code that includes a generated file (I don't know in advance its content), there is just a convention upon which me and my users agreed on how to create this file so I can use it. This file looks like
#define MACRO0 "A"
#define MACRO1 "B"
#define MACRO2 "C"
...
I want to print all macros values. My current code looks like
#ifdef MACRO0
std::cout << "MACRO0 " << MACRO0 << std::endl;
#endif
#ifdef MACRO1
std::cout << "MACRO1 " << MACRO1 << std::endl;
#endif
#ifdef MACRO2
std::cout << "MACRO2 " << MACRO2 << std::endl;
#endif
My question is, how to iterate over the macros in the generated file so I don't need to duplicate my code so much

First of all, we know we can count on Boost.Preprocessor for our looping needs. However, the generated code must work on its own. Unfortunately, #ifdef cannot work as a result of macro expansion, so there's no way to generate the code in your question. Are we toasted?
Not yet! We can take advantage of the fact that your macros are all either nonexistent or a string literal. Consider the following:
using StrPtr = char const *;
StrPtr probe(StrPtr(MACRO1));
We're taking advantage of our old friend the most vexing parse here. The second line can be interpreted in two ways depending on whether MACRO1 is defined. Without it, it is equivalent to:
char const *probe(char const *MACRO1);
... which is a function declaration where MACRO1 is the name of the parameter. But, when MACRO1 is defined to be "B", it becomes equivalent to:
char const *probe = (char const *) "B";
... which is a variable initialized to point at "B". We can then switch on the type of what we just produced to see if a substitution occured:
if(!std::is_function<decltype(probe)>::value)
std::cout << "MACRO1 " << probe << '\n';
We could make use of if constexpr here, but std::cout can output a function pointer (it converts it to bool) so the dead branch is valid, and the compiler is clever enough to completely optimize it out.
Finally, we come back to Boost.Preprocessor to generate all that stuff for us:
#define PRINT_IF_DEFINED(z, n, data) \
{ \
StrPtr probe(StrPtr(BOOST_PP_CAT(MACRO, n))); \
if(!std::is_function<decltype(probe)>::value) \
std::cout << "MACRO" BOOST_PP_STRINGIZE(n) " " << probe << '\n'; \
}
#define PRINT_MACROS(num) \
do { \
using StrPtr = char const *; \
BOOST_PP_REPEAT(num, PRINT_IF_DEFINED, ~) \
} while(false)
... voilà!
See it live on Coliru
Note: the Coliru snippet includes warning disablers for GCC and Clang, which warn against our poor pal the most vexing parse :(

I ran into the same kind of need a long time ago.
My solution was to use the preprocessor, but not to get the answer "within the code".
For example, clang++ -dM -E test.cpp will output all the macros. (At the time, I used gcc, but the same technique works for GCC, CLang, and Visual Studio's CL.EXE ... the compiler switches may vary.)
Ahh, drat, that also includes all the predefined macros.
So I would produce a "blacklist" file of the predefined macros that I did not care about, and then use that to filter out those results (using grep -v).
The other problem I ran into was that sometimes someone would #undef IMPORTANT_MACRO which would then get missed in the dump. For those infrequent situations... and then the murders began.

This answer is written taking a follow-up question into account.
C++ has support for generic programming that often eliminates need for preprocessor. In this case it would be better to make a set of type traits declaring properties of parameters that need to be handled reducing role of preprocessor to conditional compilation (or eliminating it completely if this code is supposed to be generated every time):
enum class
t_Param
{
begin, a = begin, b, c, d, e, z, end
};
template<t_Param param, typename TEnabled = void> class
t_ParamIsEnabled final: public ::std::true_type
{};
template<t_Param param> class
t_ParamIsEnabled
<
param
, typename ::std::enable_if
<
(t_Param::end == param)
#ifndef A1
|| (t_Param::a == param)
#endif
#ifndef B2
|| (t_Param::b == param)
#endif
#ifndef C3
|| (t_Param::c == param)
#endif
#ifndef D4
|| (t_Param::d == param)
#endif
#ifndef E5
|| (t_Param::e == param)
#endif
>::type
> final: public ::std::false_type
{};
template<t_Param param> class
t_ParamTrait;
template<> class
t_ParamTrait<t_Param::a> final
{
public: static constexpr auto const & num{"1"};
public: static constexpr auto const & val{"A"};
};
template<> class
t_ParamTrait<t_Param::b> final
{
public: static constexpr auto const & num{"2"};
public: static constexpr auto const & val{"B"};
};
template<> class
t_ParamTrait<t_Param::c> final
{
public: static constexpr auto const & num{"3"};
public: static constexpr auto const & val{"C"};
};
template<> class
t_ParamTrait<t_Param::d> final
{
public: static constexpr auto const & num{"4"};
public: static constexpr auto const & val{"D"};
};
template<> class
t_ParamTrait<t_Param::e> final
{
public: static constexpr auto const & num{"5"};
public: static constexpr auto const & val{"E"};
};
template<> class
t_ParamTrait<t_Param::z> final
{
public: static constexpr auto const & num{"26"};
public: static constexpr auto const & val{"ZZ"};
};
This will allow you to iterate over parameters and query their properties using generic code:
template<t_Param param> typename ::std::enable_if<t_ParamIsEnabled<param>::value>::type
Echo(void)
{
::std::cout << t_ParamTrait<param>::val << ":" << t_ParamTrait<param>::num << ::std::endl;
}
template<t_Param param> typename ::std::enable_if<!t_ParamIsEnabled<param>::value>::type
Echo(void)
{
// Do nothing
}
template<int param_index = 0> void
Echo_All(void)
{
Echo<static_cast<t_Param>(param_index)>();
Echo_All<param_index + 1>();
}
template<> void
Echo_All<static_cast<int>(t_Param::end)>(void)
{
// Do nothing.
}
int main()
{
Echo_All();
return 0;
}
online compiler

Related

Is it possible to get names of template arguments without using macro? [duplicate]

I'm writing some template classes for parseing some text data files, and as such it is likly the great majority of parse errors will be due to errors in the data file, which are for the most part not written by programmers, and so need a nice message about why the app failed to load e.g. something like:
Error parsing example.txt. Value ("notaninteger")of [MySectiom]Key is not a valid int
I can work out the file, section and key names from the arguments passed to the template function and member vars in the class, however I'm not sure how to get the name of the type the template function is trying to convert to.
My current code looks like, with specialisations for just plain strings and such:
template<typename T> T GetValue(const std::wstring &section, const std::wstring &key)
{
std::map<std::wstring, std::wstring>::iterator it = map[section].find(key);
if(it == map[section].end())
throw ItemDoesNotExist(file, section, key)
else
{
try{return boost::lexical_cast<T>(it->second);}
//needs to get the name from T somehow
catch(...)throw ParseError(file, section, key, it->second, TypeName(T));
}
}
Id rather not have to make specific overloads for every type that the data files might use, since there are loads of them...
Also I need a solution that does not incur any runtime overhead unless an exception occurs, i.e. a completely compile time solution is what I want since this code is called tons of times and load times are already getting somewhat long.
EDIT: Ok this is the solution I came up with:
I have a types.h containg the following
#pragma once
template<typename T> const wchar_t *GetTypeName();
#define DEFINE_TYPE_NAME(type, name) \
template<>const wchar_t *GetTypeName<type>(){return name;}
Then I can use the DEFINE_TYPE_NAME macro to in cpp files for each type I need to deal with (eg in the cpp file that defined the type to start with).
The linker is then able to find the appropirate template specialisation as long as it was defined somewhere, or throw a linker error otherwise so that I can add the type.
The solution is
typeid(T).name()
where typeid(T) returns std::type_info.
typeid(T).name() is implementation defined and doesn't guarantee human readable string.
Reading cppreference.com :
Returns an implementation defined null-terminated character string
containing the name of the type. No guarantees are given, in
particular, the returned string can be identical for several types and
change between invocations of the same program.
...
With compilers such as gcc and clang, the returned string can be piped through c++filt -t to be converted to human-readable form.
But in some cases gcc doesn't return right string. For example on my machine I have gcc whith -std=c++11 and inside template function typeid(T).name() returns "j" for "unsigned int". It's so called mangled name. To get real type name, use
abi::__cxa_demangle() function (gcc only):
#include <string>
#include <cstdlib>
#include <cxxabi.h>
template<typename T>
std::string type_name()
{
int status;
std::string tname = typeid(T).name();
char *demangled_name = abi::__cxa_demangle(tname.c_str(), NULL, NULL, &status);
if(status == 0) {
tname = demangled_name;
std::free(demangled_name);
}
return tname;
}
Jesse Beder's solution is likely the best, but if you don't like the names typeid gives you (I think gcc gives you mangled names for instance), you can do something like:
template<typename T>
struct TypeParseTraits;
#define REGISTER_PARSE_TYPE(X) template <> struct TypeParseTraits<X> \
{ static const char* name; } ; const char* TypeParseTraits<X>::name = #X
REGISTER_PARSE_TYPE(int);
REGISTER_PARSE_TYPE(double);
REGISTER_PARSE_TYPE(FooClass);
// etc...
And then use it like
throw ParseError(TypeParseTraits<T>::name);
EDIT:
You could also combine the two, change name to be a function that by default calls typeid(T).name() and then only specialize for those cases where that's not acceptable.
As mentioned by Bunkar typeid(T).name is implementation defined.
To avoid this issue you can use Boost.TypeIndex library.
For example:
boost::typeindex::type_id<T>().pretty_name() // human readable
This trick was mentioned under a few other questions, but not here yet.
All major compilers support __PRETTY_FUNC__ (GCC & Clang) /__FUNCSIG__ (MSVC) as an extension.
When used in a template like this:
template <typename T> const char *foo()
{
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
It produces strings in a compiler-dependent format, that contain, among other things, the name of T.
E.g. foo<float>() returns:
"const char* foo() [with T = float]" on GCC
"const char *foo() [T = float]" on Clang
"const char *__cdecl foo<float>(void)" on MSVC
You can easily parse the type names out of those strings. You just need to figure out how many 'junk' characters your compiler inserts before and after the type.
You can even do that completely at compile-time.
The resulting names can slightly vary between different compilers. E.g. GCC omits default template arguments, and MSVC prefixes classes with the word class.
Here's an implementation that I've been using. Everything is done at compile-time.
Example usage:
std::cout << TypeName<float>() << '\n';
std::cout << TypeName<decltype(1.2f)>(); << '\n';
Implementation: (uses C++20, but can be backported; see the edit history for a C++17 version)
#include <algorithm>
#include <array>
#include <cstddef>
#include <string_view>
namespace impl
{
template <typename T>
[[nodiscard]] constexpr std::string_view RawTypeName()
{
#ifndef _MSC_VER
return __PRETTY_FUNCTION__;
#else
return __FUNCSIG__;
#endif
}
struct TypeNameFormat
{
std::size_t junk_leading = 0;
std::size_t junk_total = 0;
};
constexpr TypeNameFormat type_name_format = []{
TypeNameFormat ret;
std::string_view sample = RawTypeName<int>();
ret.junk_leading = sample.find("int");
ret.junk_total = sample.size() - 3;
return ret;
}();
static_assert(type_name_format.junk_leading != std::size_t(-1), "Unable to determine the type name format on this compiler.");
template <typename T>
static constexpr auto type_name_storage = []{
std::array<char, RawTypeName<T>().size() - type_name_format.junk_total + 1> ret{};
std::copy_n(RawTypeName<T>().data() + type_name_format.junk_leading, ret.size() - 1, ret.data());
return ret;
}();
}
template <typename T>
[[nodiscard]] constexpr std::string_view TypeName()
{
return {impl::type_name_storage<T>.data(), impl::type_name_storage<T>.size() - 1};
}
template <typename T>
[[nodiscard]] constexpr const char *TypeNameCstr()
{
return impl::type_name_storage<T>.data();
}
The answer of Logan Capaldo is correct but can be marginally simplified because it is unnecessary to specialize the class every time. One can write:
// in header
template<typename T>
struct TypeParseTraits
{ static const char* name; };
// in c-file
#define REGISTER_PARSE_TYPE(X) \
template <> const char* TypeParseTraits<X>::name = #X
REGISTER_PARSE_TYPE(int);
REGISTER_PARSE_TYPE(double);
REGISTER_PARSE_TYPE(FooClass);
// etc...
This also allows you to put the REGISTER_PARSE_TYPE instructions in a C++ file...
As a rephrasing of Andrey's answer:
The Boost TypeIndex library can be used to print names of types.
Inside a template, this might read as follows
#include <boost/type_index.hpp>
#include <iostream>
template<typename T>
void printNameOfType() {
std::cout << "Type of T: "
<< boost::typeindex::type_id<T>().pretty_name()
<< std::endl;
}
If you'd like a pretty_name, Logan Capaldo's solution can't deal with complex data structure: REGISTER_PARSE_TYPE(map<int,int>)
and typeid(map<int,int>).name() gives me a result of St3mapIiiSt4lessIiESaISt4pairIKiiEEE
There is another interesting answer using unordered_map or map comes from https://en.cppreference.com/w/cpp/types/type_index.
#include <iostream>
#include <unordered_map>
#include <map>
#include <typeindex>
using namespace std;
unordered_map<type_index,string> types_map_;
int main(){
types_map_[typeid(int)]="int";
types_map_[typeid(float)]="float";
types_map_[typeid(map<int,int>)]="map<int,int>";
map<int,int> mp;
cout<<types_map_[typeid(map<int,int>)]<<endl;
cout<<types_map_[typeid(mp)]<<endl;
return 0;
}
typeid(uint8_t).name() is nice, but it returns "unsigned char" while you may expect "uint8_t".
This piece of code will return you the appropriate type
#define DECLARE_SET_FORMAT_FOR(type) \
if ( typeid(type) == typeid(T) ) \
formatStr = #type;
template<typename T>
static std::string GetFormatName()
{
std::string formatStr;
DECLARE_SET_FORMAT_FOR( uint8_t )
DECLARE_SET_FORMAT_FOR( int8_t )
DECLARE_SET_FORMAT_FOR( uint16_t )
DECLARE_SET_FORMAT_FOR( int16_t )
DECLARE_SET_FORMAT_FOR( uint32_t )
DECLARE_SET_FORMAT_FOR( int32_t )
DECLARE_SET_FORMAT_FOR( float )
// .. to be exptended with other standard types you want to be displayed smartly
if ( formatStr.empty() )
{
assert( false );
formatStr = typeid(T).name();
}
return formatStr;
}
I just leave it there.
If someone will still need it, then you can use this:
template <class T>
bool isString(T* t) { return false; } // normal case returns false
template <>
bool isString(char* t) { return true; } // but for char* or String.c_str() returns true
.
.
.
This will only CHECK type not GET it and only for 1 type or 2.
There're many good answers here, but I'd guess the easiest is to use a library, isn't it?
You can use this tiny lib, it's pretty cross-platform (tested with recent GCC/Clang/MSVC/ICC), supports C++11 onwards, works at compile time (consteval since C++20) and in theory it's going to support every compiler since the C++20's <source_location> gains wider support. A few more notes are in the README :)
I found this trick to publish a service interface with type information
#include <iostream>
using namespace std;
const char* nameOfType(int& ){ return "int";}
const char* nameOfType(const char* &){ return "string";}
const char* nameOfType(float& ){ return "float";}
const char* nameOfType(double& ){ return "double";}
template <typename T>
const char* templateFunction(T t){
return nameOfType(t) ;
};
int main()
{
cout<<"Hello World this is an ";
cout << templateFunction<int>(1) << std::endl;
cout << templateFunction<const char*>("") << std::endl;
cout << templateFunction<double>(3.14) <<std::endl;
return 0;
}
Hope it can help somebody.
Complementing the awesome answer by #HolyBlackCat which does the job at compile time. I've managed to encapsulate the logic inside a struct so there's no need for a "impl" namespace, instead the 'impl' functions are guarded in a private manner.
template<typename T>
struct TypeInfo
{
private:
struct RawTypeNameFormat
{
std::size_t leading_junk = 0;
std::size_t trailing_junk = 0;
};
template<typename U>
static constexpr const auto& RawTypeName()
{
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
// Returns `false` on failure.
static constexpr inline bool GetRawTypeNameFormat(RawTypeNameFormat *format)
{
const auto &str = RawTypeName<int>();
for (std::size_t i = 0;; i++)
{
if (str[i] == 'i' && str[i+1] == 'n' && str[i+2] == 't')
{
if (format)
{
format->leading_junk = i;
format->trailing_junk = sizeof(str)-i-3-1; // `3` is the length of "int", `1` is the space for the null terminator.
}
return true;
}
}
return false;
}
static constexpr inline RawTypeNameFormat format =
[]{
static_assert(GetRawTypeNameFormat(nullptr), "Unable to figure out how to generate type names on this compiler.");
RawTypeNameFormat format;
GetRawTypeNameFormat(&format);
return format;
}();
// Returns the type name in a `std::array<char, N>` (null-terminated).
[[nodiscard]]
static constexpr auto GetTypeName()
{
constexpr std::size_t len = sizeof(RawTypeName<T>()) - format.leading_junk - format.trailing_junk;
std::array<char, len> name{};
for (std::size_t i = 0; i < len - 1; i++)
name[i] = RawTypeName<T>()[i + format.leading_junk];
return name;
}
public:
[[nodiscard]]
static cstring Name()
{
static constexpr auto name = GetTypeName();
return name.data();
}
[[nodiscard]]
static cstring Name(const T&)
{
return name();
}
}
Example usage:
auto myTypeName = TypeInfo<MyType>::Name();
or:
const char* myTypeName = TypeInfo<MyType>::Name();
Since c++20 we can use std::source_location::function_name() to get a string containing the function name and arguments.
template<typename T>
consteval auto type_name()
{
std::string_view func_name(std::source_location::current().function_name()); // returns something like: consteval auto type_name() [with T = int]
auto extracted_params = ... Do some post processing here to extract the parameter names.
return extracted_params;
}
N.B.: at the time of writing (Oct 2022) MSVC does not report the template parameters, so this solution will not work there. Unfortunately, the form of the return value of function_name() isn't specified in the standard, but we may at least hope that they will add the template parameters in later versions.
Example

sizeof in preprocessor command doesn't compile with error C1017

I want to use preprocessor command to control code executive path. Because in this way can save runtime time.
#if (sizeof(T)==1 doesn't comple with error: C1017
template<typename T>
class String
{
public:
static void showSize()
{
#if (sizeof(T)==1)
cout << "char\n";
#else
cout << "wchar_t\n";
#endif
}
};
inline void test()
{
String<char>::showSize();
String<wchar_t>::showSize();
}
The preprocessor runs before the C++ compiler. It knows nothing of C++ types; only preprocessor tokens.
While I would expect any decent compiler to optimize away an if (sizeof(T) == 1), you can be explicit about it in C++17 with the new if constexpr:
template<typename T>
class String
{
public:
static void showSize()
{
if constexpr (sizeof(T) == 1) {
std::cout << "char\n";
} else {
std::cout << "wchar_t\n";
}
}
};
Live Demo
Pre C++17 it's a bit less straightforward. You could use some partial-specialization shenanigans. It's not particularly pretty, and I don't think it will even be more efficient in this case, but the same pattern could be applied in other situations:
template <typename T, size_t = sizeof(T)>
struct size_shower
{
static void showSize()
{
std::cout << "wchar_t\n";
}
};
template <typename T>
struct size_shower<T, 1>
{
static void showSize()
{
std::cout << "char\n";
}
};
template<typename T>
class String
{
public:
static void showSize()
{
size_shower<T>::showSize();
}
};
Live Demo
In this case you could directly specialize String, but I'm assuming in your real situation it has other members that you don't want to have to repeat.
The C and C++ preprocessor is mostly a glorified (well, not that glorious) text replacement engine. It doesn't really understand C or C++ code. It doesn't know sizeof, and it doesn't know C or C++ types. (It certainly won't know what T from your template class is.)
If you want to do things conditionally on T and on sizeof, then you'll need to write C++ code to do it (i.e., if (...) instead of #if ....)
As #some-programmer-dude mentioned in the comment, sizeof is not part of the preprocessor.
you should use if constexpr if you want it to work in compile time.
if you don't care if it happens in compile time or run-time just use a regular if statment
keep in mind that if constexpr is a new feature in C++17!
btw Borland C++ and Watcom C++ support sizeof() in preprocessor expressions, I do not know whether gcc support it.

Laziness in C++11

Do you know how to perform a lazy evaluation of string, like in this D snippet:
void log(lazy string msg) {
static if (fooBarCondition)
writefln(…) /* something with msg */
}
Actually, the problem might not need laziness at all since the static if. Maybe it’s possible to discard char const* strings when not used? Like, in C++:
void log(char const *msg) {
#ifdef DEBUG
cout << … << endl; /* something with msg */
#else /* nothing at all */
#endif
}
Any idea? Thank you.
#ifdef DEBUG
#define log(msg) do { cout << … << endl; } while(0)
#else
#define log(msg) do { } while(0)
#endif
There are two ways to achieve laziness in C++11: macros and lambda expressions. Both are not "lazy" technically, but what is called "normal evaluation" (as opposed to "eager evaluation"), which mean that an expression might be evaluated any number of times. So if you are translating a program from D (or haskell) to C++ you will have to be careful not to use expressions with side effects (including computation time) in these expressions.
To achieve true laziness, you will have to implement memoizing, which is not that simple.
For simple logging, macros are just fine.
You could mix macros and lambdas to create this effect
you could have a type, lazy
template<class T>
class lazy {
...
}
and then you could have a LAZY wrapper that created one of these using a lambda
#define LAZY(E) my_lazy_type<decltype((E))>([&](){ return E; })
All my_lazy_type needs is a constructor that accepts a std::function, and a an overload of operator() that evaluates and returns this. On each evaluation you can replace the thunk with a thunk that just returns the already computed value and thus it would only get computed once.
edit:
here is an example of what I am talking about. I would like however to point out that this is not a perfect example. it passes around a bunch of stuff by value in side the lazy which may completely defeat the purpose of doing this all in the first place. It uses mutable inside this because I need to be able to memoize the thunk in const cases. This could be improved in a lot of ways but it's a decent proof of concept.
#include <iostream>
#include <functional>
#include <memory>
#include <string>
#define LAZY(E) lazy<decltype((E))>{[&](){ return E; }}
template<class T>
class lazy {
private:
struct wrapper {
std::function<T()> thunk;
wrapper(std::function<T()>&& x)
: thunk(std::move(x)) {}
wrapper(const std::function<T()>& x)
: thunk(x) {}
};
//anytime I see mutable, I fill a bit odd
//this seems to be warented here however
mutable std::shared_ptr<wrapper> thunk_ptr;
public:
lazy(std::function<T()>&& x)
: thunk_ptr(std::make_shared<wrapper>(std::move(x))) {}
T operator()() const {
T val = thunk_ptr->thunk();
thunk_ptr->thunk = [val](){return val;};
return val;
}
};
void log(const lazy<std::string>& msg) {
std::cout << msg() << std::endl;
}
int main() {
std::string hello = "hello";
std::string world = "world";
log(LAZY(hello + ", " + world + "!"));
return 0;
}
While Elazar's answer works, I prefer not to use macros for this (especially not ones with all-lowercase names).
Here is what I would do instead:
template<bool /* = false */>
struct logger_impl {
template<typename T>
static std::ostream & write(std::ostream & stream, T const &) {
return stream;
}
};
template<>
struct logger_impl<true> {
template<typename T>
static std::ostream & write(std::ostream & stream, T const & obj) {
return stream << obj;
}
};
template<typename T>
void log(T const & obj) {
#if defined(NDEBUG)
logger_impl<true>::write(std::cout, obj);
#else
logger_impl<false>::write(std::cout, obj);
#endif
}
Just my 2 cents.

Compile time optimization - removing debug prints from release binaries

It is my very first post, so I would like to welcome with everybody. The problem I have occurred is the code optimization at compilation time, and to be more specific removing debug prints.
Let's imagine that we have native syslog logger and we are wrapping it (without using of macros, it is very important note!) with following code:
enum severity { info_log, debug_log, warning_log, error_log };
template <severity S>
struct flusher {
logger* log_;
flusher(logger* log) : log_(log) {}
flusher(flusher& rhs) : log_(rhs.log_) {}
~flusher() { syslog(S, log_->stream.str()); log_->stream.str(""); }
operator std::ostream& () { return log_->stream; }
};
#ifdef NDEBUG
template <> struct flusher<debug_log> {
flusher(logger*) {}
flusher(flusher&) {}
~flusher() {}
template <typename T> flusher& operator<<(T const&) { return *this; }
};
#endif
struct logger {
std::ostringstream stream;
template <severity T>
flusher<T> operator<<(flusher<T> (*m)(logger&)) { return m(*this); }
};
inline flusher<info_log> info(logger& log) { return flusher<info_log>(&log); }
inline flusher<debug_log> debug(logger& log) { return flusher<debug_log>(&log); }
inline flusher<warning_log> warning(logger& log) { return flusher<warning_log>(&log); }
inline flusher<error_log> error(logger& log) { return flusher<error_log>(&log); }
I thought that the empty implementation of flusher will encourage compiler to remove such useless code, but with both O2 and O3 it is not removed.
Is there any possibility to provoke mentioned behaviour?
Thanks in advance
I have successfully done what you're attempting, although with at least two differences... 1) I wasn't using templates - that might be creating a complexity the compiler is unable to optimize out, and 2) my log use included a macro (see below).
Additionally, you may have already done this, make sure all your "empty" definitions are in the logger's header file (so optimizations are done at compile-time and not postponed to link-time).
// use it like this
my_log << "info: " << 5 << endl;
The release definition looks like this:
#define my_log if(true);else logger
and the debug definition looks like this:
#define my_log if(false);else logger
Note that the compiler optimizes out the logger for all if(true) in release, and uses the logger in debug. Also note the full if/else syntax in both cases avoids funny situations where you have unscoped use, e.g.
if (something)
my_log << "this" << endl;
else
somethingelse();
would cause somethingelse to be the else of my_log without it.
Your current code is not preventing the call to f() and any side effects it may have, only preventing the actual printing. This is why macros are the traditional approach to this problem - they provide an unevaluated context where you can check if the value should be printed before actually printing.
In order to achieve this without macros, some extra indirection is needed e.g. std::function, function pointers etc. As an example, you could provide a wrapper class which contained a std::function, and specialise your stream operators to call the std::function in the default case, and not in the NDEBUG case
Very rough example:
//Wrapper object for holding std::functions without evaluating
template <typename Func>
struct debug_function_t {
debug_function_t(Func & f) : f(f) {}
decltype(f()) operator()() { return f(); }
std::function<Func> f;
};
//Helper function for type deduction
template <typename Func>
debug_function_t<Func> debug_function(Func & f) {
return debug_function_t<Func>(f);
}
struct debug_logger {
template <typename T>
debug_logger & operator<<(T & rhs) {}
template <typename Func> //Doesn't call f(), so it's never evaluated
debug_logger & operator<<(debug_function_t<Func> f) { }
};
Then in your client code
int f(){ std::cout << "f()\n"; }
debug_logger log;
log << debug_function(f);
So, following the comment's code:
inline int f()
{
std::cout << 1;
return 1;
}
needs to be made into:
inline int f()
{
#ifndef NDEBUG
std::cout << 1;
#endif
return 1;
}
or something like this:
#ifndef NDEBUG
static const int debug_enable = 1;
#else
static const int debug_enable = 0;
#endif
inline int f()
{
if (debug_enable)
{
std::cout << 1;
}
return 1;
}
You need to tell the compiler somehow that this code isn't needed.
The technique I've used for a few games requires the debug printing to be a function rather than a general expression. E.g.:
debug_print("this is an error string: %s", function_that_generates_error_string());
In release mode, the definition of debug_print is:
#define debug_print sizeof
That removes debug_print and any expression passed to it from the executable. It still has to be passed valid expressions, but they are not evaluated at runtime.

C++ Get name of type in template

I'm writing some template classes for parseing some text data files, and as such it is likly the great majority of parse errors will be due to errors in the data file, which are for the most part not written by programmers, and so need a nice message about why the app failed to load e.g. something like:
Error parsing example.txt. Value ("notaninteger")of [MySectiom]Key is not a valid int
I can work out the file, section and key names from the arguments passed to the template function and member vars in the class, however I'm not sure how to get the name of the type the template function is trying to convert to.
My current code looks like, with specialisations for just plain strings and such:
template<typename T> T GetValue(const std::wstring &section, const std::wstring &key)
{
std::map<std::wstring, std::wstring>::iterator it = map[section].find(key);
if(it == map[section].end())
throw ItemDoesNotExist(file, section, key)
else
{
try{return boost::lexical_cast<T>(it->second);}
//needs to get the name from T somehow
catch(...)throw ParseError(file, section, key, it->second, TypeName(T));
}
}
Id rather not have to make specific overloads for every type that the data files might use, since there are loads of them...
Also I need a solution that does not incur any runtime overhead unless an exception occurs, i.e. a completely compile time solution is what I want since this code is called tons of times and load times are already getting somewhat long.
EDIT: Ok this is the solution I came up with:
I have a types.h containg the following
#pragma once
template<typename T> const wchar_t *GetTypeName();
#define DEFINE_TYPE_NAME(type, name) \
template<>const wchar_t *GetTypeName<type>(){return name;}
Then I can use the DEFINE_TYPE_NAME macro to in cpp files for each type I need to deal with (eg in the cpp file that defined the type to start with).
The linker is then able to find the appropirate template specialisation as long as it was defined somewhere, or throw a linker error otherwise so that I can add the type.
The solution is
typeid(T).name()
where typeid(T) returns std::type_info.
typeid(T).name() is implementation defined and doesn't guarantee human readable string.
Reading cppreference.com :
Returns an implementation defined null-terminated character string
containing the name of the type. No guarantees are given, in
particular, the returned string can be identical for several types and
change between invocations of the same program.
...
With compilers such as gcc and clang, the returned string can be piped through c++filt -t to be converted to human-readable form.
But in some cases gcc doesn't return right string. For example on my machine I have gcc whith -std=c++11 and inside template function typeid(T).name() returns "j" for "unsigned int". It's so called mangled name. To get real type name, use
abi::__cxa_demangle() function (gcc only):
#include <string>
#include <cstdlib>
#include <cxxabi.h>
template<typename T>
std::string type_name()
{
int status;
std::string tname = typeid(T).name();
char *demangled_name = abi::__cxa_demangle(tname.c_str(), NULL, NULL, &status);
if(status == 0) {
tname = demangled_name;
std::free(demangled_name);
}
return tname;
}
Jesse Beder's solution is likely the best, but if you don't like the names typeid gives you (I think gcc gives you mangled names for instance), you can do something like:
template<typename T>
struct TypeParseTraits;
#define REGISTER_PARSE_TYPE(X) template <> struct TypeParseTraits<X> \
{ static const char* name; } ; const char* TypeParseTraits<X>::name = #X
REGISTER_PARSE_TYPE(int);
REGISTER_PARSE_TYPE(double);
REGISTER_PARSE_TYPE(FooClass);
// etc...
And then use it like
throw ParseError(TypeParseTraits<T>::name);
EDIT:
You could also combine the two, change name to be a function that by default calls typeid(T).name() and then only specialize for those cases where that's not acceptable.
As mentioned by Bunkar typeid(T).name is implementation defined.
To avoid this issue you can use Boost.TypeIndex library.
For example:
boost::typeindex::type_id<T>().pretty_name() // human readable
This trick was mentioned under a few other questions, but not here yet.
All major compilers support __PRETTY_FUNC__ (GCC & Clang) /__FUNCSIG__ (MSVC) as an extension.
When used in a template like this:
template <typename T> const char *foo()
{
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
It produces strings in a compiler-dependent format, that contain, among other things, the name of T.
E.g. foo<float>() returns:
"const char* foo() [with T = float]" on GCC
"const char *foo() [T = float]" on Clang
"const char *__cdecl foo<float>(void)" on MSVC
You can easily parse the type names out of those strings. You just need to figure out how many 'junk' characters your compiler inserts before and after the type.
You can even do that completely at compile-time.
The resulting names can slightly vary between different compilers. E.g. GCC omits default template arguments, and MSVC prefixes classes with the word class.
Here's an implementation that I've been using. Everything is done at compile-time.
Example usage:
std::cout << TypeName<float>() << '\n';
std::cout << TypeName<decltype(1.2f)>(); << '\n';
Implementation: (uses C++20, but can be backported; see the edit history for a C++17 version)
#include <algorithm>
#include <array>
#include <cstddef>
#include <string_view>
namespace impl
{
template <typename T>
[[nodiscard]] constexpr std::string_view RawTypeName()
{
#ifndef _MSC_VER
return __PRETTY_FUNCTION__;
#else
return __FUNCSIG__;
#endif
}
struct TypeNameFormat
{
std::size_t junk_leading = 0;
std::size_t junk_total = 0;
};
constexpr TypeNameFormat type_name_format = []{
TypeNameFormat ret;
std::string_view sample = RawTypeName<int>();
ret.junk_leading = sample.find("int");
ret.junk_total = sample.size() - 3;
return ret;
}();
static_assert(type_name_format.junk_leading != std::size_t(-1), "Unable to determine the type name format on this compiler.");
template <typename T>
static constexpr auto type_name_storage = []{
std::array<char, RawTypeName<T>().size() - type_name_format.junk_total + 1> ret{};
std::copy_n(RawTypeName<T>().data() + type_name_format.junk_leading, ret.size() - 1, ret.data());
return ret;
}();
}
template <typename T>
[[nodiscard]] constexpr std::string_view TypeName()
{
return {impl::type_name_storage<T>.data(), impl::type_name_storage<T>.size() - 1};
}
template <typename T>
[[nodiscard]] constexpr const char *TypeNameCstr()
{
return impl::type_name_storage<T>.data();
}
The answer of Logan Capaldo is correct but can be marginally simplified because it is unnecessary to specialize the class every time. One can write:
// in header
template<typename T>
struct TypeParseTraits
{ static const char* name; };
// in c-file
#define REGISTER_PARSE_TYPE(X) \
template <> const char* TypeParseTraits<X>::name = #X
REGISTER_PARSE_TYPE(int);
REGISTER_PARSE_TYPE(double);
REGISTER_PARSE_TYPE(FooClass);
// etc...
This also allows you to put the REGISTER_PARSE_TYPE instructions in a C++ file...
As a rephrasing of Andrey's answer:
The Boost TypeIndex library can be used to print names of types.
Inside a template, this might read as follows
#include <boost/type_index.hpp>
#include <iostream>
template<typename T>
void printNameOfType() {
std::cout << "Type of T: "
<< boost::typeindex::type_id<T>().pretty_name()
<< std::endl;
}
If you'd like a pretty_name, Logan Capaldo's solution can't deal with complex data structure: REGISTER_PARSE_TYPE(map<int,int>)
and typeid(map<int,int>).name() gives me a result of St3mapIiiSt4lessIiESaISt4pairIKiiEEE
There is another interesting answer using unordered_map or map comes from https://en.cppreference.com/w/cpp/types/type_index.
#include <iostream>
#include <unordered_map>
#include <map>
#include <typeindex>
using namespace std;
unordered_map<type_index,string> types_map_;
int main(){
types_map_[typeid(int)]="int";
types_map_[typeid(float)]="float";
types_map_[typeid(map<int,int>)]="map<int,int>";
map<int,int> mp;
cout<<types_map_[typeid(map<int,int>)]<<endl;
cout<<types_map_[typeid(mp)]<<endl;
return 0;
}
typeid(uint8_t).name() is nice, but it returns "unsigned char" while you may expect "uint8_t".
This piece of code will return you the appropriate type
#define DECLARE_SET_FORMAT_FOR(type) \
if ( typeid(type) == typeid(T) ) \
formatStr = #type;
template<typename T>
static std::string GetFormatName()
{
std::string formatStr;
DECLARE_SET_FORMAT_FOR( uint8_t )
DECLARE_SET_FORMAT_FOR( int8_t )
DECLARE_SET_FORMAT_FOR( uint16_t )
DECLARE_SET_FORMAT_FOR( int16_t )
DECLARE_SET_FORMAT_FOR( uint32_t )
DECLARE_SET_FORMAT_FOR( int32_t )
DECLARE_SET_FORMAT_FOR( float )
// .. to be exptended with other standard types you want to be displayed smartly
if ( formatStr.empty() )
{
assert( false );
formatStr = typeid(T).name();
}
return formatStr;
}
I just leave it there.
If someone will still need it, then you can use this:
template <class T>
bool isString(T* t) { return false; } // normal case returns false
template <>
bool isString(char* t) { return true; } // but for char* or String.c_str() returns true
.
.
.
This will only CHECK type not GET it and only for 1 type or 2.
There're many good answers here, but I'd guess the easiest is to use a library, isn't it?
You can use this tiny lib, it's pretty cross-platform (tested with recent GCC/Clang/MSVC/ICC), supports C++11 onwards, works at compile time (consteval since C++20) and in theory it's going to support every compiler since the C++20's <source_location> gains wider support. A few more notes are in the README :)
I found this trick to publish a service interface with type information
#include <iostream>
using namespace std;
const char* nameOfType(int& ){ return "int";}
const char* nameOfType(const char* &){ return "string";}
const char* nameOfType(float& ){ return "float";}
const char* nameOfType(double& ){ return "double";}
template <typename T>
const char* templateFunction(T t){
return nameOfType(t) ;
};
int main()
{
cout<<"Hello World this is an ";
cout << templateFunction<int>(1) << std::endl;
cout << templateFunction<const char*>("") << std::endl;
cout << templateFunction<double>(3.14) <<std::endl;
return 0;
}
Hope it can help somebody.
Complementing the awesome answer by #HolyBlackCat which does the job at compile time. I've managed to encapsulate the logic inside a struct so there's no need for a "impl" namespace, instead the 'impl' functions are guarded in a private manner.
template<typename T>
struct TypeInfo
{
private:
struct RawTypeNameFormat
{
std::size_t leading_junk = 0;
std::size_t trailing_junk = 0;
};
template<typename U>
static constexpr const auto& RawTypeName()
{
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
// Returns `false` on failure.
static constexpr inline bool GetRawTypeNameFormat(RawTypeNameFormat *format)
{
const auto &str = RawTypeName<int>();
for (std::size_t i = 0;; i++)
{
if (str[i] == 'i' && str[i+1] == 'n' && str[i+2] == 't')
{
if (format)
{
format->leading_junk = i;
format->trailing_junk = sizeof(str)-i-3-1; // `3` is the length of "int", `1` is the space for the null terminator.
}
return true;
}
}
return false;
}
static constexpr inline RawTypeNameFormat format =
[]{
static_assert(GetRawTypeNameFormat(nullptr), "Unable to figure out how to generate type names on this compiler.");
RawTypeNameFormat format;
GetRawTypeNameFormat(&format);
return format;
}();
// Returns the type name in a `std::array<char, N>` (null-terminated).
[[nodiscard]]
static constexpr auto GetTypeName()
{
constexpr std::size_t len = sizeof(RawTypeName<T>()) - format.leading_junk - format.trailing_junk;
std::array<char, len> name{};
for (std::size_t i = 0; i < len - 1; i++)
name[i] = RawTypeName<T>()[i + format.leading_junk];
return name;
}
public:
[[nodiscard]]
static cstring Name()
{
static constexpr auto name = GetTypeName();
return name.data();
}
[[nodiscard]]
static cstring Name(const T&)
{
return name();
}
}
Example usage:
auto myTypeName = TypeInfo<MyType>::Name();
or:
const char* myTypeName = TypeInfo<MyType>::Name();
Since c++20 we can use std::source_location::function_name() to get a string containing the function name and arguments.
template<typename T>
consteval auto type_name()
{
std::string_view func_name(std::source_location::current().function_name()); // returns something like: consteval auto type_name() [with T = int]
auto extracted_params = ... Do some post processing here to extract the parameter names.
return extracted_params;
}
N.B.: at the time of writing (Oct 2022) MSVC does not report the template parameters, so this solution will not work there. Unfortunately, the form of the return value of function_name() isn't specified in the standard, but we may at least hope that they will add the template parameters in later versions.
Example