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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/165101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:24:12  来源:igfitidea点击:

"invalid use of incomplete type" error with partial template specialization

c++gcctemplatespartial-specialization

提问by Jesse Beder

The following code:

以下代码:

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

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

gives me the error

给我错误

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

(I'm using gcc.) Is my syntax for partial specialization wrong? Note that if I remove the second argument:

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

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

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

then it compiles correctly.

然后它正确编译。

回答by coppro

You can't partially specialize a function. If you wish to do so on a member function, you must partially specialize the entire template (yes, it's irritating). On a large templated class, to partially specialize a function, you would need a workaround. Perhaps a templated member struct (e.g. template <typename U = T> struct Nested) would work. Or else you can try deriving from another template that partially specializes (works if you use the this->membernotation, otherwise you will encounter compiler errors).

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

回答by Echsecutor

Although coppro mentioned two solutions already and Anonymous explained the second one, it took me quite some time to understand the first one. Maybe the following code is helpful for someone stumbling across this site, which still ranks high in google, like me. The example (passing a vector/array/single element of numericalT as dataT and then accessing it via [] or directly) is of course somewhat contrived, but should illustrate how you actually can come very close to partially specializing a member function by wrapping it in a partially specialized class.

虽然 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) ...
};

回答by Anonymous Coward

If you need to partially specialise a constructor, you might try something like:

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

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.
    }
};

Note: this was anonymised from something I'm working on. You can also use this when you have a template class with lots and lots of members and you just want to add a function.

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