真正的问题是您需要 C++03 解决方案,因此您可以使用 SFINAE,但不能使用从 C++11 开始的所有语言改进。
无论如何,我建议您提供一个与您的一样复杂(可能更多)但完全免费的解决方案。
如果你定义了一个简单的 bool 包装器(可以大致替代 C++11 的 std::true_type 和 std::false_type)
template <bool B>
struct bool_wrapper
{ static const bool value = B; };
您可以如下定义您的条件
template <typename, typename = bool_wrapper<true> >
struct cond : public bool_wrapper<false>
{ };
template <typename T>
struct cond<T, bool_wrapper<(1 == T::code) || (2 == T::code)> >
: public bool_wrapper<true>
{ };
如果你定义了一个 enable_if 类型的特征(与 C++11 的 std::enable_if 相同)
template <bool, typename = void>
struct enable_if
{ };
template <typename T>
struct enable_if<true, T>
{ typedef T type; };
您可以 SFINAE 启用/禁用您的 foo() 函数
template <typename T>
typename enable_if<false == cond<T>::value>::type foo (T const & arg)
{ std::cout << "no static member code or value not 1 and not 2\n"; }
template <typename T>
typename enable_if<true == cond<T>::value>::type foo (T const & arg)
{ std::cout << "static member code and its value is " << T::code << "\n"; }
以下是一个完整的 C++98 示例
#include <iostream>
template <int N> struct A1 { static const int code = N; };
template <int N> struct A2 { static const int code = N; };
// ...
template <int N> struct AN { static const int code = N; };
struct B1{};
struct B2{};
// ...
struct BN{};
template <bool B>
struct bool_wrapper
{ static const bool value = B; };
template <typename, typename = bool_wrapper<true> >
struct cond : public bool_wrapper<false>
{ };
template <typename T>
struct cond<T, bool_wrapper<(1 == T::code) || (2 == T::code)> >
: public bool_wrapper<true>
{ };
template <bool, typename = void>
struct enable_if
{ };
template <typename T>
struct enable_if<true, T>
{ typedef T type; };
template <typename T>
typename enable_if<false == cond<T>::value>::type foo (T const & arg)
{ std::cout << "no static member code or value not 1 and not 2\n"; }
template <typename T>
typename enable_if<true == cond<T>::value>::type foo (T const & arg)
{ std::cout << "static member code and its value is " << T::code << "\n"; }
int main ()
{
foo(A1<0>()); // match the 1st version of foo
foo(A2<1>()); // match the 2nd version of foo
foo(AN<2>()); // match the 2nd version of foo
foo(B1()); // match the 1st version of foo
foo(BN()); // match the 1st version of foo
}
我不知道你使用的 boost 类,但我想你可以修改你的代码(几乎就像我的 no-boost 解决方案一样工作)如下
template <typename, typename = bool_<true> >
struct Condition : public bool_<false>
{ };
template <typename T>
struct Condition<T, bool_<(1 == T::code) || (2 == T::code)> >
: public bool_<true>
{ };
-- 编辑--
OP 询问
我不明白 A1 的情况如何。 Condition 的特化应该是首选匹配,第二个参数扩展为 bool_。该类继承自 bool_,因此,它应该选择错误的 foo 版本。但是它有效。怎么可能?
嗯...当您编写foo(A1<0>()) 时,编译器必须了解cond<A1<0>>::value 是true 还是false 才能启用foo() 的第一个版本或第二个版本。
所以编译器必须实现cond<A1<0>>。但是没有一个cond 模板类只接收一个类型名。无论如何,编译器发现
template <typename, typename = bool_wrapper<true> >
struct cond;
使用第二个模板参数的默认值匹配。
没有选择,所以没有歧义,所以cond< A<1> >变成cond< A<1>, bool_wrapper<true> >
现在编译器必须在主版本cond<typename, typename>(继承自bool_wrapper<false>)和特化版本(继承自bool_wrapper<true>)之间进行选择。
cond< A<1>, bool_wrapper<true> > 肯定匹配主版本,但也匹配专业?如果也匹配特化,编译器必须优先选择特化。
所以我们需要查看cond< A<0>, bool_wrapper<true> > 是否匹配特化。
将A<0> 用作T,我们就有了专业化
cond< A<0>, bool_wrapper<(1 == A<0>::code) || (2 == A<0>::code)> >
那是
cond< A<0>, bool_wrapper<(1 == 0) || (2 == 0)> >
那是
cond< A<0>, bool_wrapper<false || false> >
那是
cond< A<0>, bool_wrapper<false> >
这与cond< A<0>, bool_wrapper<true> > 不匹配。
所以cond< A<0> >,也就是cond< A<0>, bool_wrapper<true> >,只匹配cond<typename, typename>的主版本,所以继承自bool_wrapper<false>。
现在我们可以看看cond< A<1> >。
对于cond< A<0> >,唯一匹配cond< A<1> >的模板cond是cond<typename, typename>,第二个typename是默认值。
所以cond< A<1> > 是cond< A<1>, bool_wrapper<true> >。
但是cond< A<1>, bool_wrapper<true> > 只匹配cond<typename, typename> 的主要版本还是也匹配专业化?
我们可以看到,使用A<1> 作为T,我们就有了特化变成了
cond< A<1>, bool_wrapper<(1 == A<1>::code) || (2 == A<1>::code)> >
那是
cond< A<1>, bool_wrapper<(1 == 1) || (2 == 1)> >
那是
cond< A<1>, bool_wrapper<true || false> >
那是
cond< A<1>, bool_wrapper<true> >
这匹配cond< A<1>, bool_wrapper<true> >。
所以,对于cond< A<1> >,又名cond< A<1>, bool_wrapper<true>,cond<typename, typename> 的两个版本都匹配,所以编译器必须选择特化,所以cond< A<1> > 继承自bool_wrapper<true>。