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

发布于 2024-07-05 21:43:05 字数 519 浏览 12 评论 0原文

以下代码:

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() {
}

那么它会正确编译。

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:

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

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

then it compiles correctly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

怪异←思 2024-07-12 21:43:05

你不能部分特化一个函数。 如果您希望对成员函数执行此操作,则必须部分特化整个模板(是的,这很烦人)。 在大型模板类上,要部分专门化某个函数,您需要一种解决方法。 也许模板化成员结构(例如templatestruct Nested)会起作用。 或者,您可以尝试从另一个部分专门化的模板派生(如果您使用 this->member 表示法,则有效,否则您将遇到编译器错误)。

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->member notation, otherwise you will encounter compiler errors).

白云悠悠 2024-07-12 21:43:05

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

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

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

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.

疾风者 2024-07-12 21:43:05

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

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.

/* 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) ...
};
画中仙 2024-07-12 21:43:05

如果您正在阅读这个问题,那么您可能需要提醒,虽然您不能部分专门化方法,但您可以添加非模板化重载,该重载将优先于模板化函数被调用。 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
  }
};

If you're reading this question then you might like to be reminded that although you can't partially specialise methods you can add a non-templated overload, which will be called in preference to the templated function. i.e.

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
  }
};
请爱~陌生人 2024-07-12 21:43:05

在 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

In C++ 17, I use "if constexpr" to avoid specialize (and rewrite) my method. For example :

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

That avoid to specialize A<1>::recursiveMethod().
You can also use this method for type like this example :

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();
}

output :

other
arithmetic
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文