c++ - 如果模板参数不允许实例化某个类,如何编写模板重载函数并触发回退

标签 c++ templates template-specialization sfinae

如果我取消注释包含 foo<double>() 的行,下面的程序不会编译,因为 B<double>取决于 A<double> ,这是一个不完整的类型。

#include <iostream>
using namespace std;

template <class T> struct A;  // forward declaration (incomplete)
template <>        struct A<int> {};  // specialized for int

template <class T> struct B : A<T> { int foo() {return 0;} }; // derived class, general definition inherits from A
template <> struct B<bool> { int foo() {return 1;} }; // derived class, does not inherit from A

template <class T> int foo() { B<T> b; return b.foo(); }  // to be called if B<T> is valid

int main()
{
    cout << foo<int>() << "\n";      // print 0
    cout << foo<bool>() << "\n";      // print 1
    // cout << foo<double>() << "\n";   // this line would generate a compile error
}

我想要一种重载函数 foo 的方法这样如果 B<T>不是有效类型,则函数的替代版本 foo叫做。 IE。我想有一种方法来定义重载

template <class T> int foo() { return -1; }  // to be called if B<T> is not valid

我还可以包装函数 foo在结构内部,如果有帮助的话。有没有办法在 C++03 中做到这一点?

最佳答案

记住你的analogue question和昆汀的回答,我看到问题是B<T>A<T> 时可以(显然)完成不完整。

我看到的唯一方法(抱歉:目前只有 C++11)是强加通用 B<T>如果A<T> 被定义为已定义(将其转换为部分特化);通过以下方式

template <typename T, bool = is_complete<A<T>>::value>
struct B;

template <typename T>
struct B<T, true> : A<T>
 { int foo() {return 0;} };

template <>
struct B<bool>
 { int foo() {return 1;} };

如果可以修改B这样,解决方案就简单了(再次使用Quentin开发的is_complete)。

下面是一个工作示例

#include <iostream>
#include <type_traits>

template <typename T, std::size_t = sizeof(T)>
std::true_type is_complete_impl(T *);

std::false_type is_complete_impl(...);

template <typename T>
using is_complete = decltype(is_complete_impl(std::declval<T*>()));

template <typename>
struct A;

template <>
struct A<int>
 { };

template <typename T, bool = is_complete<A<T>>::value>
struct B;

template <typename T>
struct B<T, true> : A<T>
 { int foo() {return 0;} };

template <>
struct B<bool>
 { int foo() {return 1;} };

template <typename T>
typename std::enable_if<true == is_complete<B<T>>::value, int>::type foo() 
 { B<T> b; return b.foo(); }

template <typename T>
typename std::enable_if<false == is_complete<B<T>>::value, int>::type foo() 
 { return 2; }

int main()
 {
   std::cout << foo<int>() << "\n";     // print 0
   std::cout << foo<bool>() << "\n";    // print 1
   std::cout << foo<double>() << "\n";  // print 2
 }

关于c++ - 如果模板参数不允许实例化某个类,如何编写模板重载函数并触发回退,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44237528/

相关文章:

c++ - 类构造函数和类成员变量的意外输出值

c++ - 模板推导不适用于函数指针引用

c++ - 如何在不复制函数的情况下推导 const 和非常量类型?

c++ - 插入优先级队列时出现段错误

c++ - 具有完全专用别名的实现切换

c++ - 模板类特化与模板类

c++ - 在模板类的特殊情况下将虚函数定义为纯虚函数

c++ - #define 变量在 windows.h 中被忽略并重新定义

c++ - 现有 win 控制台应用程序的简单 GUI 插件

c++ - cocos2d-x中使用CCBReader报错