繁体   English   中英

部分模板特化的“无效使用不完整类型”错误

[英]“invalid use of incomplete type” error with partial template specialization

以下代码:

template <typename S, typename T>
struct foo {
   void bar();
};

template <typename T>
void foo <int, T>::bar() {
}

给我错误

invalid use of incomplete type 'struct foo<int, T>'
declaration of 'struct foo<int, T>'

(我正在使用 gcc。)我的部分专业化语法错误​​吗? 请注意,如果我删除第二个参数:

template <typename S>
struct foo {
   void bar();
};

template <>
void foo <int>::bar() {
}

然后它正确编译。

你不能部分特化一个函数。 如果您希望在成员函数上这样做,则必须部分特化整个模板(是的,这很烦人)。 在大型模板化类上,要部分专门化一个函数,您需要一种解决方法。 也许模板成员结构(例如template <typename U = T> struct Nested )会起作用。 或者,您可以尝试从另一个部分专门化的模板派生(如果您使用this->member符号,则可以使用,否则您将遇到编译器错误)。

虽然 coppro 已经提到了两个解决方案,Anonymous 解释了第二个,但我花了很长时间才理解第一个。 也许下面的代码对那些在这个网站上磕磕绊绊的人有帮助,这个网站在谷歌中仍然排名很高,就像我一样。 该示例(将 numericT 的向量/数组/单个元素作为 dataT 传递,然后通过 [] 或直接访问它)当然有些人为,但应该说明您实际上如何通过包装它来非常接近部分专门化成员函数在一个部分专业化的课程中。

/* The following circumvents the impossible partial specialization of 
a member function 
actualClass<dataT,numericalT,1>::access
as well as the non-nonsensical full specialisation of the possibly
very big actualClass. */

//helper:
template <typename dataT, typename numericalT, unsigned int dataDim>
class specialised{
public:
  numericalT& access(dataT& x, const unsigned int index){return x[index];}
};

//partial specialisation:
template <typename dataT, typename numericalT>
class specialised<dataT,numericalT,1>{
public:
  numericalT& access(dataT& x, const unsigned int index){return x;}
};

//your actual class:
template <typename dataT, typename numericalT, unsigned int dataDim>
class actualClass{
private:
  dataT x;
  specialised<dataT,numericalT,dataDim> accessor;
public:
  //... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ...
};

如果您需要部分特化一个构造函数,您可以尝试以下操作:

template <class T, int N>
struct thingBase
{
    //Data members and other stuff.
};

template <class T, int N> struct thing : thingBase<T, N> {};

template <class T> struct thing<T, 42> : thingBase<T, 42>
{
    thing(T * param1, wchar_t * param2)
    {
        //Special construction if N equals 42.
    }
};

注意:这是从我正在处理的事情中匿名的。 当您有一个包含大量成员的模板类并且您只想添加一个函数时,您也可以使用它。

如果您正在阅读这个问题,那么您可能希望被提醒,虽然您不能部分专门化方法,但您可以添加非模板化重载,该重载将优先于模板化函数调用。 IE

struct A
{
  template<typename T>
  bool foo(T arg) { return true; }

  bool foo(int arg) { return false; }

  void bar()
  {
    bool test = foo(7);  // Returns false
  }
};

在 C++ 17 中,我使用“if constexpr”来避免专门化(和重写)我的方法。 例如 :

template <size_t TSize>
struct A
{
    void recursiveMethod();
};

template <size_t TSize>
void A<TSize>::recursiveMethod()
{
    if constexpr (TSize == 1)
    {
        //[...] imple without subA
    }
    else
    {
        A<TSize - 1> subA;

        //[...] imple
    }
}

避免专门化 A<1>::recursiveMethod()。 您也可以将此方法用于像此示例这样的类型:

template <typename T>
struct A
{
    void foo();
};

template <typename T>
void A<T>::foo()
{
    if constexpr (std::is_arithmetic_v<T>)
    {
        std::cout << "arithmetic" << std::endl;
    }
    else
    {
        std::cout << "other" << std::endl;
    }
}


int main()
{
    A<char*> a;
    a.foo();

    A<int> b;

    b.foo();
}

输出 :

other
arithmetic

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM