first of all we need a little introduction, so here we go. I'd like to write a functional struct that'll be able to retrieve name of a certain type, including templates. It'll return type's name from type_info
or own defined custom name.
Here's a tiny logger which will need the name of a struct.
#define LOG(x) FunctionLog(#x, x)
template<typename _Ty>
void FunctionLog(const char* name, const _Ty& value)
{
// TypeName'll be introduced later.
std::cout << name << ": " << static_cast<const char*>(TypeName<_Ty>::c_Name) << " = " << value << '\n';
}
// Simple const char* wrapper, to easily concanate them with an operator|().
// I decided to use const char* instead of std::string due to memory.
struct CString
{
const char* Content;
explicit CString(const char* content)
: Content(content) {}
CString operator|(const CString& other)
{
return CString{ strcat(_strdup(Content), _strdup(other.Content)) };
}
operator const char*() const { return Content; }
};
template<typename _Ty>
struct TypeName
{
static inline const CString c_Name = CString{ typeid(_Ty).name() };
}
// example of implementing that struct for std::vector<_Ty>
template<typename _Ty>
struct TypeName<std::vector<_Ty>>
{
static inline const CString c_Name = CString{ "std::vector<" } | TypeName<_Ty>::c_Name | CString{ ">" };
};
And my problem is, how to make it work for std::tuple
s as I don't know how to do that, because the tuple has a various number of template arguments. And I would like it to look like so: std::tuple<int, int>
-> std::tuple<int, int>, std::tuple<std::vector<int>, int>
-> std::tuple<std::vector< int>, int>. So every argument of that tuple template should call corresponding TypeName<_Ty>
.
If something is unclear, please ask as I could miss something.
CodePudding user response:
It seems you want something like (C 17):
template<typename ... Ts>
struct TypeName<std::tuple<Ts...>>
{
static inline const CString c_Name =
(CString{ "std::tuple<" } | ... | TypeName<Ts>::c_Name) | CString{ ">" };
};