The real problem is that you need a C++03 solution, so you can use SFINAE but not all language improvement that are available starting from C++11.
Anyway, I propose you a solution that is convoluted like yours (maybe more) but is completely boost free.
If you define a trivial bool wrapper (that can roughly substitute the C++11 std::true_type and std::false_type)
template <bool B>
struct bool_wrapper
{ static const bool value = B; };
you can define your condition as follows
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>
{ };
and if you define a enable_if type traits (the same as the C++11 std::enable_if)
template <bool, typename = void>
struct enable_if
{ };
template <typename T>
struct enable_if<true, T>
{ typedef T type; };
you can SFINAE enable/disable your foo() functions
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"; }
The following is a full working C++98 example
#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
}
I don't know the boost classes your using but I suppose you can modify your code (to works almost as my no-boost solution) as follows
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>
{ };
-- EDIT --
The OP ask
I do not understand how it works for the case A1<0>. The specialization of Condition should be the preferred match, with the 2nd argument expanding to bool_. That class inherits from bool_, so, it should pick the wrong versions of foo. However it works. How is it possible?
Well... when you write foo(A1<0>()), the compiler must understand if cond<A1<0>>::value is true or false to enable the first version of foo() or the second one.
So the compiler must implement cond<A1<0>>. But there isn't a cond template class that receive only a typename. Anyway, the compiler find that
template <typename, typename = bool_wrapper<true> >
struct cond;
matches using the default value for the second template parameter.
There aren't alternative, so there isn't ambiguity, so cond< A<1> > become cond< A<1>, bool_wrapper<true> >
Now the compiler must choose between the main version of cond<typename, typename> (the one that inherit from bool_wrapper<false>) and the specialization (the one that inherit from bool_wrapper<true>).
cond< A<1>, bool_wrapper<true> > surely matches the main version, but matches also the specialization? If matches the also the specialization, the compiler must prefer the specialization.
So we need to see if cond< A<0>, bool_wrapper<true> > matches the specialization.
Using A<0> as T, we have that the specialization become
cond< A<0>, bool_wrapper<(1 == A<0>::code) || (2 == A<0>::code)> >
that is
cond< A<0>, bool_wrapper<(1 == 0) || (2 == 0)> >
that is
cond< A<0>, bool_wrapper<false || false> >
that is
cond< A<0>, bool_wrapper<false> >
and this doesn't matches cond< A<0>, bool_wrapper<true> >.
So cond< A<0> >, that is cond< A<0>, bool_wrapper<true> >, matches only the main version of cond<typename, typename>, so inherit from bool_wrapper<false>.
Now we can give a look at cond< A<1> >.
As for cond< A<0> >, the only template cond that matches cond< A<1> > is cond<typename, typename> with the second typename with the default value.
So cond< A<1> > is cond< A<1>, bool_wrapper<true> >.
But cond< A<1>, bool_wrapper<true> > matches only the main version of cond<typename, typename> or also the specialization?
We can see that using A<1> as T, we have that the specialization become
cond< A<1>, bool_wrapper<(1 == A<1>::code) || (2 == A<1>::code)> >
that is
cond< A<1>, bool_wrapper<(1 == 1) || (2 == 1)> >
that is
cond< A<1>, bool_wrapper<true || false> >
that is
cond< A<1>, bool_wrapper<true> >
and this matches cond< A<1>, bool_wrapper<true> >.
So, for cond< A<1> >, AKA cond< A<1>, bool_wrapper<true>, both versions of cond<typename, typename> match, so the compiler must choose the specialization, so cond< A<1> > inherit from bool_wrapper<true>.