C++ 在模板类的特殊情况下,将虚函数定义为纯函数

C++ 在模板类的特殊情况下,将虚函数定义为纯函数,c++,c++14,template-specialization,pure-virtual,C++,C++14,Template Specialization,Pure Virtual,我试图定义一个模板基类,该基类定义了一个由用户重写的虚拟接口。在某些情况下,使用此方法的默认实现是有意义的,但并非所有类型参数都是如此。考虑这一点: template<typename T> struct supplier { virtual std::unique_ptr<T> supply(std::istream& moreData) = 0; }; 问题不在于如何为适当的T定义此函数,而在于如何使其在未定义时显示为纯虚拟函数,从而强制用户实现,如

我试图定义一个模板基类,该基类定义了一个由用户重写的虚拟接口。在某些情况下,使用此方法的默认实现是有意义的,但并非所有类型参数都是如此。考虑这一点:

template<typename T>
struct supplier
{
    virtual std::unique_ptr<T> supply(std::istream& moreData) = 0;
};
问题不在于如何为适当的
T
定义此函数,而在于如何使其在未定义时显示为纯虚拟函数,从而强制用户实现,如果它是普通虚拟函数的话。

我想我只是错过了一些显而易见的解决办法。我试图专门化
struct-supplier
,但这意味着我必须定义接口的其余部分两次,因此它肯定不是一个可扩展的解决方案。这也意味着我必须提供接口的其余部分两次


对于具有许多虚拟函数的富基类,是否有一个价格合理的解决方案,这些函数可以提供实现,也可以是纯虚拟的?

将需要专门化的部分提取到单独的类模板中,然后从中继承

namespace details {
    template<class T, bool = std::is_default_constructible<T>::value>
    struct supplier_base
    {
        virtual std::unique_ptr<T> supply(std::istream& moreData) = 0;
    };

    template<class T>
    struct supplier_base<T, true>
    {
        virtual std::unique_ptr<T> supply(std::istream& moreData)
        {
            return std::unique_ptr<T>(new T);
        }
    };
}

template<class T>
struct supplier : details::supplier_base<T> { /* ... */ };
名称空间详细信息{
模板
结构供应商库
{
虚拟std::唯一ptr供应(std::istream&moreData)=0;
};
模板
结构供应商库
{
虚拟std::唯一ptr供应(std::istream&moreData)
{
返回std::unique_ptr(新T);
}
};
}
模板
结构供应商:详细信息::供应商库{/*…*/};

将需要专门化的部分提取到单独的类模板中,然后从中继承

namespace details {
    template<class T, bool = std::is_default_constructible<T>::value>
    struct supplier_base
    {
        virtual std::unique_ptr<T> supply(std::istream& moreData) = 0;
    };

    template<class T>
    struct supplier_base<T, true>
    {
        virtual std::unique_ptr<T> supply(std::istream& moreData)
        {
            return std::unique_ptr<T>(new T);
        }
    };
}

template<class T>
struct supplier : details::supplier_base<T> { /* ... */ };
名称空间详细信息{
模板
结构供应商库
{
虚拟std::唯一ptr供应(std::istream&moreData)=0;
};
模板
结构供应商库
{
虚拟std::唯一ptr供应(std::istream&moreData)
{
返回std::unique_ptr(新T);
}
};
}
模板
结构供应商:详细信息::供应商库{/*…*/};

在这种情况下,是否建议将基类隐藏在匿名命名空间中?@WorldSEnder否,这是违反ODR的原因。在这种情况下,是否建议将基类隐藏在匿名命名空间中?@WorldSEnder否,这是违反ODR的原因。