问题
I want to be able to make the compiler shout when i call a constructor of foo with a class that is NOT derived from _base*. The current code allows only for foo<_base*> itself. Any easy solution ?
class _base
{
public:
// ...
};
class _derived: public _base
{
public:
// ...
};
template <typename T>
class foo
{
public:
foo () { void TEMPLATE_ERROR; }
};
template <> foo<_base*>::foo ()
{
// this is the only constructor
}
main-code:
foo<_base*> a; // should work
foo<_derived*> b; // should work (but doesnt)
foo<int*> c; // should not work (and infact doesnt)
回答1:
Without Boost you can use something like the following to determine whether a pointer-to-type can be implicitly cast to another pointer-to-type:
template <class Derived, class Base>
struct IsConvertible
{
template <class T>
static char test(T*);
template <class T>
static double test(...);
static const bool value = sizeof(test<Base>(static_cast<Derived*>(0))) == 1;
};
To make it trigger an error at compile-time, you can now use value
in an expression that causes an error if it is false, for example typedef a negative-sized array.
template <typename T>
class foo
{
public:
foo ()
{
typedef T assert_at_compile_time[IsConvertible<T, _base>::value ? 1 : -1];
}
};
回答2:
Use SFINAE (via enable_if) and Boost’s is_convertible type trait:
template <typename T, typename Enabled = void>
class foo
{
private:
foo(); // Constructor declared private and not implemented.
};
template <typename T>
class foo<T, typename enable_if<is_convertible<T, _base*> >::type>
{
public:
foo() { /* regular code */ }
};
(untested, haven’t got Boost installed on this machine.)
回答3:
I understand that you are not using boost in your project, but maybe you could copy-paste some parts of it.
I found a simpler solution to your problem using boost:
template <typename T>
class foo
{
public:
foo () {
BOOST_STATIC_ASSERT((boost::is_convertible<T,_base*>::value));
}
};
It doesn't require additional template parameter, also no need for template specialization. I tested it with boost 1.40.
来源:https://stackoverflow.com/questions/1657830/c-template-specialization-via-a-base-class