可以组合部分模板特化来生成隐式生成的共享代码路径吗?

Can partial template specializations be combined to produce implicitly generated shared code paths?

我在考虑模板特化,想知道是否有一种方法可以使用部分特化来生成自动合并的两个不同代码路径。

在这种情况下,我有一个计算引擎,我希望在编译时枚举 select 不同的函数。在这种情况下,根据 policyscheme 我想要在编译时使用不同的函数。

我在想我可以避免显式地部分特化所有变体。这可能吗?

我已经包含了一个小代码示例。

#include <iostream>

enum class scheme { linear, polynomial };

enum class policy { no_checking, raise_exception };

struct computational_base
{
    void left();
    void middle();
    void do_stuff()
    {
        left();
        middle();
    }
};

template <scheme scheme, policy left>
struct computational_backend : public computational_base
{

};

template <policy left>
struct computational_backend<scheme::linear, left> : public computational_base
{
    void middle()
    {
        std::cout << "scheme::linear" << std::endl;
    }
};

template <scheme scheme>
struct computational_backend<scheme, policy::no_checking> : public computational_base
{
    void left()
    {
        std::cout << "policy::no_checking" << std::endl;
    }
};

int main()
{
    //Ideally would select middle() from first template, and left() from second template
    // more than one partial specialization matches the template argument list
    computational_backend<scheme::linear, policy::no_checking> what;
    what.do_stuff();
    return 0;
}

CRTP 和多重继承可以成为你的朋友。在核心,您可以使用多重继承从 类

中引入功能
template <scheme s, policy p>
struct computational_backend
: scheme_backend<s>
, policy_backend<p>
{ };

只要计算过程的不同部分不需要互相调用,这种方法就可以了。换句话说,它在 middle() 永远不需要调用 left() 时起作用,反之亦然。

如果您需要它们相互调用,好奇递归模板模式 (CRTP) 是您的好帮手。这是一个奇怪的地方,它基本上允许您从基础 类 转换为派生程度最高的类型,因为您将派生程度最高的类型作为模板参数传入。它看起来像这样:

template <typename DerivedT, scheme s>
struct scheme_backend;

template <typename DerivedT, policy p>
struct policy_backend;

template <typename DerivedT>
struct scheme_backend<DerivedT, scheme::linear>
{
    DerivedT& derived()
    {
        return *static_cast<DerivedT*>(this);
    }

    void left()
    {
        ...
        derived().middle();
        ...
    }
};

template <scheme s, policy p>
struct computational_backend
: scheme_backend<computational_backend<s, p>, s>
, policy_backend<computational_backend<s, p>, p>
{ };

我只画了一个专业,但你懂的。事实证明,奇怪的静态转换不仅在 C++ 中是合法的,而且实际上速度非常快。在很多情况下,编译器可以完全优化它。