在C++中选择重载模板函数时的优先级

mmm*_*mmm 16 c++ methods templates overloading

我有以下问题:

class Base
{
};

class Derived : public Base
{
};

class Different
{
};

class X
{
public:
  template <typename T>
  static const char *func(T *data)
  {
    // Do something generic...
    return "Generic";
  }

  static const char *func(Base *data)
  {
    // Do something specific...
    return "Specific";
  }
};
Run Code Online (Sandbox Code Playgroud)

如果我现在这样做

Derived derived;
Different different;
std::cout << "Derived: " << X::func(&derived) << std::endl;
std::cout << "Different: " << X::func(&different) << std::endl;
Run Code Online (Sandbox Code Playgroud)

我明白了

Derived: Generic
Different: Generic
Run Code Online (Sandbox Code Playgroud)

但我想要的是,对于从Base派生的所有类,调用特定方法.所以结果应该是:

Derived: Specific
Different: Generic
Run Code Online (Sandbox Code Playgroud)

有什么方法可以重新设计X:func(...)来实现这个目标吗?

编辑:

假设作为参数提交的类是否是从Base派生的,X :: func(...)的调用者不知道它.所以Casting to Base不是一个选择.事实上,整个事情背后的想法是X :: func(...)应该'检测'参数是否从Base派生,并调用不同的代码.出于性能原因,"检测"应该在编译时进行.

mmm*_*mmm 16

我找到了一个非常简单的解决方案!

class Base
{
};

class Derived : public Base
{
};

class Different
{
};

class X
{
private:
  template <typename T>
  static const char *intFunc(const void *, T *data)
  {
    // Do something generic...
    return "Generic";
  }

  template <typename T>
  static const char *intFunc(const Base *, T *data)
  {
    // Do something specific...
    return "Specific";
  }

public:
  template <typename T>
  static const char *func(T *data)
  {
    return intFunc(data, data);
  }
};
Run Code Online (Sandbox Code Playgroud)

这很好用,非常苗条!诀窍是让编译器通过(否则无用的)第一个参数选择正确的方法.


ava*_*kar 8

您必须使用SFINAE.在以下代码中,当且仅当您传递无法(隐式)转换为的内容时,才能实例化第一个函数Base *.第二个功能就是这样.

你可能想要阅读enable_if.

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>

class Base {};
class Derived : public Base {};
class Different {};

struct X
{
    template <typename T>
    static typename boost::disable_if<boost::is_convertible<T *, Base *>,
        const char *>::type func(T *data)
    {
        return "Generic";
    }

    template <typename T>
    static typename boost::enable_if<boost::is_convertible<T *, Base *>,
        const char *>::type func(T *data)
    {
        return "Specific";
    }
};

int main()
{
    Derived derived;
    Different different;
    std::cout << "Derived: " << X::func(&derived) << std::endl;
    std::cout << "Different: " << X::func(&different) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)