C ++类模板或纯虚拟

时间:2015-03-19 12:18:40

标签: c++ templates

我正在尝试实现一个模板类,如果模板参数正确的话,它既可以用作派生的基础,也可以用作具体的类。

我想要实现的是,如果模板类的方法无法实例化,但派生类提供了实现,那就没问题。 但是,如果模板可以完全实例化,那么该类对它自己有效。

示例:

// interface class
class A
{
public:
    virtual void foo() = 0;
    virtual ~A() {}
};

// template class
template <typename T>
class B : public A
{
public:
    /* if this tenplate can be instantiated */
    foo() 
    {
        T obj;
        std::cout << obj;
    }
    /* else
    foo() = 0;
    */
};

// concrete classes
// will work on it's own
typedef B<std::string> C;

class D : public B<void>
{
    // B<void>::foo won't instantiate on it's own
    // so we provide help here
    foo() {}
};

int main(int argc, char const *argv[])
{
    A * = new C(); // all good
    A * = new D(); // error: cannot instantiate B<void>::foo
    return 0;
}

有没有办法达到这样的效果?

3 个答案:

答案 0 :(得分:3)

使用SFINAE,您可能会执行以下操作:

namespace detail
{
    // an helper for traits
    template <typename T>
    decltype(T{}, std::cout << T{}, std::true_type{})
    helper_has_default_constructor_and_foo(int);

    template <typename T>
    std::false_type helper_has_default_constructor_and_foo(...);

    // the traits
    template <typename T>
    using has_default_constructor_and_foo = decltype(helper_has_default_constructor_and_foo<T>(0));

    // genaral case (so when traits is false)
    template <typename T, typename = has_default_constructor_and_foo<T>>
    struct C : public A {};

    // specialization when traits is true
    template <typename T>
    struct C<T, std::true_type> : public A
    {
        void foo() override { std::cout << T{}; }
    };

}

最后:

template <typename T>
class B : public detail::C<T>
{
};

live demo

答案 1 :(得分:0)

您可以专注于B<void>

// template class
template <typename T>
class B : public A
{
public:
    virtual void foo() 
    {
        T obj;
        std::cout << obj;
    }
};
template <>
class B<void> : public A
{
public:
    virtual void foo() = 0;
};

答案 2 :(得分:0)

必须专门化B<>并且不能使用SFINAE(在成员foo上)。 SFINAE仅适用于模板,但成员函数模板不能是virtual

有不同的方法可以实现专业化,但最直接的是简单明了的

template<typename T>
class B : public A
{
  /* ... */                // not overridden foo() by default
};

template<>
class B<WhatEver> : public A
{
  virtual foo();
};
相关问题