参数功能缺少指针cv资格,部分模板专门化

时间:2018-07-09 12:24:40

标签: c++ function-pointers variadic-templates template-specialization qualifiers

结构名称用于将类型声明转换为字符串。测试逻辑错误时,当类型声明为函数类型(或指针函数的类型)并且具有带限定符(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;
}

输出(gcc):

int(*)(int(*)())
int(*const)(int(*)())
int(*volatile)(int(*)())
int(*const volatile)(int(*)())

0 个答案:

没有答案