如果我取消注释包含 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/