继承的函数模板特化

function template specialization for inheritance

在C++11中,我实现了用于识别继承的函数模板特化,但出现了编译时错误。

f() 检查指定的 class 是否派生自 Base

以下是源代码。

#include <iostream>
#include <type_traits>
using namespace std;

struct Base {};
struct Derived : Base {};
struct Base2 {};

template<typename T, bool = std::is_base_of<Base, T>::value>
void f() {
    cout << "T is not Base or Base-derived class." << endl;
};

template<typename T>
void f<T, true>() {
    cout << "T is Base or Base-derived class." << endl;
};

int main() {
    f<Base>();    // ok
    f<Derived>(); // ok
    f<Base2>();   // not ok
    return 0;
}

以下是错误信息。

prog.cpp:15:17: error: non-class, non-variable partial specialization 'f<T, true>' is not allowed
 void f<T, true>() {
                 ^
prog.cpp: In function 'int main()':
prog.cpp:20:13: error: call of overloaded 'f()' is ambiguous
     f<Base>();
             ^
prog.cpp:10:6: note: candidate: void f() [with T = Base; bool <anonymous> = true]
 void f() {
      ^
prog.cpp:15:6: note: candidate: void f() [with T = Base]
 void f<T, true>() {
      ^
prog.cpp:21:16: error: call of overloaded 'f()' is ambiguous
     f<Derived>();
                ^
prog.cpp:10:6: note: candidate: void f() [with T = Derived; bool <anonymous> = true]
 void f() {
      ^
prog.cpp:15:6: note: candidate: void f() [with T = Derived]
 void f<T, true>() {
      ^
prog.cpp:22:14: error: call of overloaded 'f()' is ambiguous
     f<Base2>();
              ^
prog.cpp:10:6: note: candidate: void f() [with T = Base2; bool <anonymous> = false]
 void f() {
      ^
prog.cpp:15:6: note: candidate: void f() [with T = Base2]
 void f<T, true>() {
      ^

我该如何解决?

std::is_base_of<Base, T>::value 计算 true 时,您有两个具有相同签名的函数。因此你得到错误 "call ... is amibguous".

尝试简单重载作为解决方案之一:

namespace detail {
    void doIt(std::false_type) {
        cout << "T is not Base or Base-derived class." << endl;
    };
    void doIt(std::true_type) {
        cout << "T is Base or Base-derived class." << endl;
    };
}

template<typename T>
void f() {
    detail::doIt(typename std::is_base_of<Base, T>::type());
};

当然,函数 detail::doIt() 可以更复杂并由 T 模板化。

编辑:将 "detail::" 添加到函数 f() 调用中。