结构名称用于将类型声明转换为字符串。测试逻辑错误时,当类型声明为函数类型(或指针函数的类型)并且具有带限定符(const, volatile, const volatile
的指针函数的参数类型声明时。函数参数中的指针函数类型缺少限定符。有关更多详细信息,请参见下面的code
:
#include <iostream>
#include <stack>
#include <string>
#include <typeinfo>
template<typename T>
struct Name;
从函数类型的声明符中拆分参数。
template<typename... Targs>
struct Parameter
{
static void ToString(std::string& str, bool first = true)
{}
};
template<typename Targ, typename... Targs>
struct Parameter<Targ, Targs...>
{
static void ToString(std::string& str, bool first = true)
{
if (!first)
str += ", ";
str += Name<Targ>::ToString();
Parameter<Targs...>::ToString(str, false);
}
};
使用部分模板专门化对声明的类型进行分类。
template<typename T>
struct Declarator
{
typedef T RemovedType;
static void ToString(std::string& str,
std::stack<std::string>& ptr_str_stack)
{}
};
template<typename T>
struct Declarator<T*>
{
typedef typename Declarator<T>::RemovedType RemovedType;
static void ToString(std::string& str,
std::stack<std::string>& ptr_str_stack)
{
ptr_str_stack.push("*");
Declarator<T>::ToString(str, ptr_str_stack);
}
};
template<typename T>
struct Declarator<T*const>
{
typedef typename Declarator<T>::RemovedType RemovedType;
static void ToString(std::string& str,
std::stack<std::string>& ptr_str_stack)
{
ptr_str_stack.push("*const");
Declarator<T>::ToString(str, ptr_str_stack);
}
};
template<typename T>
struct Declarator<T*volatile>
{
typedef typename Declarator<T>::RemovedType RemovedType;
static void ToString(std::string& str,
std::stack<std::string>& ptr_str_stack)
{
ptr_str_stack.push("*volatile");
Declarator<T>::ToString(str, ptr_str_stack);
}
};
template<typename T>
struct Declarator<T*const volatile>
{
typedef typename Declarator<T>::RemovedType RemovedType;
static void ToString(std::string& str,
std::stack<std::string>& ptr_str_stack)
{
ptr_str_stack.push("*const volatile");
Declarator<T>::ToString(str, ptr_str_stack);
}
};
template<typename T, typename... Targs>
struct Declarator<T(*)(Targs...)>
{
typedef typename Declarator<T>::RemovedType RemovedType;
static void ToString(std::string& str,
std::stack<std::string>& ptr_str_stack)
{
str += "(*";
while(!ptr_str_stack.empty())
{
str += ptr_str_stack.top();
ptr_str_stack.pop();
}
str += ")(";
Parameter<Targs...>::ToString(str);
str += ")";
}
};
template<typename T, typename... Targs>
struct Declarator<T(*const)(Targs...)>
{
typedef typename Declarator<T>::RemovedType RemovedType;
static void ToString(std::string& str,
std::stack<std::string>& ptr_str_stack)
{
str += "(*const";
while(!ptr_str_stack.empty())
{
str += ptr_str_stack.top();
ptr_str_stack.pop();
}
str += ")(";
Parameter<Targs...>::ToString(str);
str += ")";
}
};
template<typename T, typename... Targs>
struct Declarator<T(*volatile)(Targs...)>
{
typedef typename Declarator<T>::RemovedType RemovedType;
static void ToString(std::string& str,
std::stack<std::string>& ptr_str_stack)
{
str += "(*volatile";
while(!ptr_str_stack.empty())
{
str += ptr_str_stack.top();
ptr_str_stack.pop();
}
str += ")(";
Parameter<Targs...>::ToString(str, true);
str += ")";
}
};
template<typename T, typename... Targs>
struct Declarator<T(*const volatile)(Targs...)>
{
typedef typename Declarator<T>::RemovedType RemovedType;
static void ToString(std::string& str,
std::stack<std::string>& ptr_str_stack)
{
str += "(*const volatile";
while(!ptr_str_stack.empty())
{
str += ptr_str_stack.top();
ptr_str_stack.pop();
}
str += ")(";
Parameter<Targs...>::ToString(str, true);
str += ")";
}
};
使用显式模板专门化对名称类型进行分类。
template<typename T>
struct Type
{
static void ToString(std::string& str)
{
str += typeid(T).name();
}
};
template<>
struct Type<int>
{
static void ToString(std::string& str)
{
str += "int";
}
};
要将类型声明转换为字符串。
template<typename T>
struct Name
{
static std::string ToString()
{
typedef typename Declarator<T>::RemovedType SimpleType;
std::string str;
std::string declarator_str;
std::stack<std::string> declarator_ptr_str_stack;
Type<SimpleType>::ToString(str);
Declarator<T>::ToString(declarator_str, declarator_ptr_str_stack);
while(!declarator_ptr_str_stack.empty())
{
str += declarator_ptr_str_stack.top();
declarator_ptr_str_stack.pop();
}
str += declarator_str;
return str;
}
};
int main()
{
std::cout << Name<int(*)(int(*)())>::ToString() << std::endl;
std::cout << Name<int(*const)(int(*const)())>::ToString() << std::endl;
std::cout << Name<int(*volatile)(int(*const volatile)())>::ToString() << std::endl;
std::cout << Name<int(*const volatile)(int(*volatile)())>::ToString() << std::endl;
}
int(*)(int(*)())
int(*const)(int(*)())
int(*volatile)(int(*)())
int(*const volatile)(int(*)())