将派生类传递给专门用于基类的模板函数 [英] Passing a derived class to a template function specialized with base class

查看:56
本文介绍了将派生类传递给专门用于基类的模板函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码可正常编译,但会产生链接器错误:

The following code compiles fine, but produces a linker error:

class Base {};

class Derived : public Base {};

template <typename T>
void f(const T& value);

template <>
void f(const Base& value) {
    // ...
}

int main() {
    Base b;
    f(b);

    Derived d;
    f(d); // This line causes linker error.

    return 0;
}

是否可以在不为派生类添加重复的 f()专业化条件的情况下,使该代码进行编译和链接?

Is it possible to make this code compile and link without adding a duplicate f() specialization for the derived class?

谢谢.

P.S我正在使用clang,Apple LLVM 6.0版(clang-600.0.56)(基于LLVM 3.5svn).

P.S I'm using clang, Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn).

P.P.S链接器错误是:

P.P.S The linker error is:

Undefined symbols for architecture x86_64:
  "void f<Derived>(Derived const&)", referenced from:
      _main in test2-4245dc.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

推荐答案

发生链接器错误是因为您尚未定义(仅声明)函数模板

The linker error occurs because you haven't defined, only declared, the function template

template <typename T>
void f(const T& value);

为避免这种情况,请定义上面的模板,您的代码将被编译,但是大概它仍然无法满足您的要求.

To avoid it, define the above template and your code will compile, but presumably it still doesn't do what you want.

当使用类型为 Derived 的参数调用 f 时,与您的专业化相比,上面的模板更好地匹配,因为后者需要从派生到基数的转换,而前者没有.

When calling f with an argument of type Derived the above template is a better match compared to your specialization because the latter requires a derived-to-base conversion while the former doesn't.

您可以使用 enable_if 仅在推导的模板参数类型不是 Base 或从 Base 派生的类型时,才允许第一个模板参与重载解析.

You can achieve the behavior you want by using enable_if to allow the first template to participate in overload resolution only if the deduced template argument type is not Base or a type derived from Base.

template <typename T>
typename std::enable_if<!std::is_base_of<Base, T>::value>::type
    f(const T& value) {

}

并更改另一个 f ,所以它不是专门化的,而只是重载.

And change the other f so it's not a specialization, but just an overload.

void f(const Base& value) {
    // ...
}

实时演示

通常,重载函数模板胜于专业化.阅读,以了解功能模板专业化的陷阱.

In general, prefer overloading function templates over specialization. Read this to learn about the pitfalls of function template specialization.

这篇关于将派生类传递给专门用于基类的模板函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆