首页 文章

部分专业化时,基于C模板的“覆盖”等效?

提问于
浏览
6

我有一个模板类/结构,如下所示:

template <typename T, typename U>
struct S
{
    unsigned int operator()(T t, U u) const;
};

我想确保专业化尊重这个界面 .

不幸的是,我可以使用不同的返回类型来专门化这个结构 . 例如,如果我部分专门返回 bool 而不是 unsigned int ,我希望得到编译器错误,但编译器似乎并不关心:

template <typename T>
struct S<T,nullptr_t>
{
    bool operator()(T t, nullptr_t u) const { return 2; }
};

Example @ Ideone.com

在上面的示例中,专用版本应返回 2 但由于返回类型为 bool ,因此返回值将转换为 true ,然后显示为 1 .

为什么编译器会接受这个?

如何防止程序员使用错误的返回类型(甚至错误的参数)专门化模板?

我知道我可以在基本模板类/结构中使用虚方法实现我想要的,并在子代中使用 override 关键字:

Solution with override(不编译,哪个好)

但是拥有一个虚拟方法肯定会创建一个虚拟表,我想尽可能地避免这种情况,特别是因为我在运行时不需要虚拟表 . 除非有一个技巧可以在不构建虚拟表的情况下做同样的事情?

另外,我知道问题会更简单,如果我可以部分专门化方法或者我可以依赖非部分专业化,但前者在C AFAIK中是不可能的,后者不包括我在程序中需要的情况 .

1 回答

  • 1

    创建静态接口的好方法是使用curiously recurring template pattern . 在您的情况下,它看起来像这样:

    template<class Derived, class T, class U>
    constexpr bool MyTrait = std::is_same<unsigned int, decltype(std::declval<Derived>()(std::declval<T>(), std::declval<U>()))>::value;
    
    template <typename Derived, class T, class U>
    struct StaticInterface
    {
    
        unsigned int operator()(T t, U u) const{
            static_assert( MyTrait<Derived, T, U>, "errr" );
    
            return (*static_cast<const Derived *>(this))(std::forward<T>(t), std::forward<U>(u));
        }
    };
    
    template <typename T, typename U>
    struct S : StaticInterface<S<T, U>, T, U>
    {
        unsigned int operator()(T t, U u) const{ /* some implementation */}
    };
    
    template <typename T>
    struct S<T, std::nullptr_t> : StaticInterface<S<T, std::nullptr_t>, T, std::nullptr_t>
    {
        bool operator()(T t, std::nullptr_t u) const { return 2; }
    };
    

    为了使它工作,函数调用必须通过如下界面完成:

    template<class Derived, class T, class U>
    void test(const StaticInterface<Derived, T, U> &inter){
        inter(T(), U());
    }
    

    否则,派生的操作员将被选为优选的操作员 .

相关问题