C++11模板参数,基本定义的部分特化错误

c++11 template argument ,wrong partial specialitzation from base definition

本文关键字:错误 定义 参数 C++11      更新时间:2023-10-16

我正在尝试实现通用队列 FIFO,但在尝试从定义为基本模板类的类中选择正确的专用化类方面无法取得任何进展。这是代码:这段代码首先描述的是链表实现,所以类 Node 和 enum 类被定义为描述将要使用的队列类型(链表或固定数组(,第一部分(Node 和 GenericQueueType(工作得很好,在 main 函数中先定义做一些测试。然后,将用作包装类的包装函数不会选择为使用链表而定义的部分专用化。

#include <iostream>
#include <string>
//The node definition used for the linked list
 template<typename ValueType>
 struct Node_
 {
    Node_(): NodePtr(nullptr)
    {}
    Node_(const ValueType & aValue): _Value( aValue )
       ,NodePtr(nullptr)
    {
    }
     ValueType  _Value;
    Node_ * NodePtr;
};
//====================
enum class EQueueType
{
    EQueueType_Linked_List,
    EQueueType_Fixed_Queue
};
//====================
template<EQueueType,class ...  TypeValue>
struct GenericQueueType
{
};
template<class   TypeValue>
struct GenericQueueType<EQueueType::EQueueType_Linked_List, TypeValue>
{
    GenericQueueType():TopPtr(nullptr)
      ,BackPtr(nullptr)
    {}
    void insertValueInQueue(const TypeValue  & aValue)
    {
       Node_<TypeValue > * aPtr=BackPtr;
       BackPtr=new Node_<TypeValue>(aValue );
       if(TopPtr==nullptr)
       {
            TopPtr=BackPtr;
       }
       else
       {
           BackPtr->NodePtr=aPtr;
       }
    }

    void getValueFromQueue(TypeValue  &  aValue)
    {
        //aErrorcode=ERROR_PROCESS;
        if (TopPtr!=nullptr)
        {
           Node_<TypeValue > * aPtr= TopPtr;
            aValue=aPtr->_Value;
             aPtr->_Value ;
           TopPtr=TopPtr->NodePtr;
            delete TopPtr;
           TopPtr=nullptr;
        }
    }
private:
static const int ERROR_PROCESS = -1;
static const int OK_ERROR_CODE = 0;
  Node_ <TypeValue > * TopPtr;
  Node_ <TypeValue > * BackPtr;

};
//base queue wrapper
template<typename  QueueType, typename  ... Element>
class QueueFIFO
{
};
template< template<typename  ... > class QueueType,typename   EQ_type,typename  ... TypeElement >
class QueueFIFO<QueueType<EQ_type,TypeElement  ...>,EQ_type,TypeElement ... >
{

    using value_type = typename std::tuple<TypeElement...>;
    static const int INITIAL_SIZE=0;
public:
    QueueFIFO():_Size(INITIAL_SIZE)
    {}
    void enqueue(const value_type  &  aElement)
    {
            Queue.insertValueInQueue(aElement);
    }
    void dequeue( value_type   & aElement)
    {
        Queue.getValueFromQueue(aElement);
    }
    int size(){}
private:
    int _Size;
    QueueType<EQ_type,TypeElement  ...> Queue;

};

int main()
{
     float aElement=14;
    GenericQueueType<EQueueType::EQueueType_Linked_List,float> aLinkedList;
    aLinkedList.insertValueInQueue(aElement);
    QueueFIFO<GenericQueueType<EQueueType::EQueueType_Linked_List,float>,float> _Queue;
    _Queue.enqueue(aElement);
    return 0;
}

以下是编译器输出:

error: 'class QueueFIFO<GenericQueueType<(EQueueType)0, float>, float>' has no member named 'enqueue'
     _Queue.enqueue(aElement);
            ^

我一直在从标准中阅读以下内容:

在引用类模板专用化的类型名称中,(例如, a( 参数列表应与模板参数匹配 主模板的列表。模板参数 专业化是从主模板的参数中推导出来的。 14.5.5.1 但是我仍然看不到错误。 提前感谢!

问题出在模板模板参数中的某个地方,实际上并没有创建专业化。如果仅使用;而不是空定义声明非专用版本,则这一点会更清楚。

简短的回答是不要使用模板模板参数;你编写的代码不需要它们(或者,事实上,任何模板的专用化(,而且你不太可能看到需要它们的情况(在这种情况下,它实际上通过消除可能有用的情况而造成伤害(。

enqueue在你对QueueFIFO的部分专业化中定义,const & value_type value_typestd::tuple。您正在尝试用aElement来调用它,这是一个float,而您应该传递它一个std::tuple<float>。尝试将std::make_tuple(aElement)传递给enqueue

此外,正如 T.C. 在评论中指出的那样,您使用typename EQ_type和传入类型 EQueueType 的枚举值的位置是错误的 - 枚举值与模板类型参数不匹配。您将不得不为此使用非类型参数,就像您在 GenericQueueType 的定义中所做的那样。