在 C++ 中专门化函数时调用该函数的非专门化版本?

发布于 2024-10-01 04:04:20 字数 501 浏览 6 评论 0 原文

假设我有一个模板化类:

template <typename T>
class foo {
  void do_someting(T obj) {
    // do something generic...
  }
};

并且我想专门化 do_something,但在其中我想调用“正常”do_something 函数:

template<>
void foo<MyObj>::do_something(MyObj obj) {
  // do something specific...
  // and ALSO do something generic!
}

有没有办法在我的专门函数中引用 do_something 的正常版本?或者我只需要复制代码?

(我知道我可以以这样的方式重构 foo,这样我就不会遇到这个确切的问题,但碰巧我无法真正修改“真正的”foo,因为它是大量共享的代码。)

Say I have a templated class:

template <typename T>
class foo {
  void do_someting(T obj) {
    // do something generic...
  }
};

and I want to specialize do_something, but within it I want to call the "normal" do_something function:

template<>
void foo<MyObj>::do_something(MyObj obj) {
  // do something specific...
  // and ALSO do something generic!
}

is there a way to refer to the normal version of do_something within my specialized function? Or do I just have to copy the code?

(I know that I could refactor foo in such a way that I wouldn't have this exact problem, but as it happens I can't really modify the "real" foo, as it's heavily-shared code.)

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

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

发布评论

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

评论(3

情深已缘浅 2024-10-08 04:04:20

不。您的专业化是 MyObj 类型参数存在的唯一定义。但是,考虑以这种方式修改 foo 模板,这对于模板的当前用户来说是透明的:

template<typename T>
class foo {
  void prelude(T &obj){ // choose a better name
    /* do nothing */
  }
  void do_something(T obj){
    prelude(obj);
    // do something generic...
  }
};

然后为 prelude 定义一个专门化:

template<>
void foo<MyObj>::prelude(MyObj &obj){
  // do something specific
}

这在结构上有点类似于 私人虚拟会员的主要用例。 (有点。不是真的。但这正是我回答这个问题的灵感来源。)

No. Your specialization is the only definition that will exist for the MyObj type argument. But, consider modifying the foo template in this manner, which will be transparent to the current users of the template:

template<typename T>
class foo {
  void prelude(T &obj){ // choose a better name
    /* do nothing */
  }
  void do_something(T obj){
    prelude(obj);
    // do something generic...
  }
};

Then define a specialization for the prelude:

template<>
void foo<MyObj>::prelude(MyObj &obj){
  // do something specific
}

This is somewhat similar in structure to the main use case for private virtual members. (Sort of. Not really. But it's what inspired me in this answer.)

将军与妓 2024-10-08 04:04:20

您还可以考虑不是 MyObj 的类型,但隐式转换为它,但最好的方法是重构并可能提取常见的通用内容。

#include <iostream>
#include <boost/ref.hpp>
typedef int MyObj;


template <typename T>
struct foo {
  void do_something(T obj) {
    // do something generic...
    std::cout << "generic " << obj << '\n';
  }
};

template<>
void foo<MyObj>::do_something(MyObj obj) {
  // do something specific...
  std::cout << "special " << obj << '\n';
  // and ALSO do something generic!
  foo<boost::reference_wrapper<MyObj> >().do_something(boost::ref(obj));
}

int main()
{
    foo<int> f;
    f.do_something(10);
}

You might also consider a type that is not MyObj, but implicitly converts to it, but the best way would be to refactor and perhaps extract the common generic something.

#include <iostream>
#include <boost/ref.hpp>
typedef int MyObj;


template <typename T>
struct foo {
  void do_something(T obj) {
    // do something generic...
    std::cout << "generic " << obj << '\n';
  }
};

template<>
void foo<MyObj>::do_something(MyObj obj) {
  // do something specific...
  std::cout << "special " << obj << '\n';
  // and ALSO do something generic!
  foo<boost::reference_wrapper<MyObj> >().do_something(boost::ref(obj));
}

int main()
{
    foo<int> f;
    f.do_something(10);
}
寒尘 2024-10-08 04:04:20

是的,这实际上非常简单。您只需让函数的主要通用版本作为“实现”通用函数的传递,该函数不会部分专门化,然后您可以从专门化版本调用它根据需要的初始功能。

template <typename T>
class foo 
{
  void do_something(T obj) 
  {
     do_something_impl(obj);
  }

  void do_something_impl(T obj)
  {
    // do something generic...
  }
};

现在专业化可以毫无问题地调用通用版本:

template<>
void foo<MyObj>::do_something(MyObj obj) 
{
  // do something specific...
  do_something_impl(obj); //The generic part
}

我认为这比 Steve M. 的答案更接近你的初衷,这也是我在面对这个问题时所做的。

Yes, this this is actually quite straightforward. You just let the main, generic version of your function serve as a pass-through to an 'implementation' generic function which doesn't get partially specialized, then you can just call that from the specialized version of the initial function as needed.

template <typename T>
class foo 
{
  void do_something(T obj) 
  {
     do_something_impl(obj);
  }

  void do_something_impl(T obj)
  {
    // do something generic...
  }
};

Now the specialization can call the generic version without a problem:

template<>
void foo<MyObj>::do_something(MyObj obj) 
{
  // do something specific...
  do_something_impl(obj); //The generic part
}

I think this closer to your original intentions than Steve M.'s answer, and is what I do when faced with this issue.

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