偏特化模板c++

Partial specialization tempate c++

我正在探索 JUCE 框架并找到这段有趣的代码,

namespace SampleTypeHelpers // Internal classes needed for handling sample type classes
{
    template <typename T, bool = std::is_floating_point<T>::value>
    struct ElementType
    {
        using Type = T;
    };

    template <typename T>
    struct ElementType<T, false>
    {
        using Type = typename T::value_type;
    };
}

我读了一点,这在c++中被称为偏特化,我认为它很清楚,但有一点我不明白,在第一个模板中有bool 已初始化,正在做什么?

感谢所有将回答的人!

就像函数可以有默认参数一样,模板也可以有默认参数。

int foo(int a = 5) { ... }

foo(7) // a = 7
foo()  // a = 5

等效模板示例为

template <int I = 5>
int bar() { ... }

bar<10>() // I = 10
bar()     // I = 5

在您的示例中,参数的名称也被省略了,如果模板参数仅用于 select 部分专业化,这是一种常见的做法。我们不需要它的名字,因为我们从来没有提到过它。我们只需要它有一定的value/type.

看看这个函数声明:

void frob(float f, bool g = true) {
    // ...
}

您可能知道,您可以从声明中删除参数名称:

void frob(float f, bool = true) {
    // ...
}

您还可以使用表达式设置默认值。这与前面的示例等效:

void frob(float f, bool = std::is_floating_point<float>::value) {
    // ...
}

然后,为了练习,让我们添加一个简单的模板:

template<typename T>
void frob(T f, bool = std::is_floating_point<T>::value) {
    // ...
}

从技术上讲,您可以将参数移动为模板参数,如果您在编译时知道它们:

template<typename T, bool = std::is_floating_point<T>::value>
void frob(T f) {
    // ...
}

现在它开始看起来像您自己的模板声明了,不是吗?


现在您已经理解了语法,让我们看看它对偏特化有何用处。

假设您是编译器,您将 ElementType 的模板实例化扩展为 floatstd::integral_constant<int, 0>:

template<>
struct ElementType<float, std::is_floating_point<float>::value> { ... };

template<>
struct ElementType<
    std::integral_constant<int, 0>,
    std::is_floating_point<int>::value
> { ... };

扩展常量,你得到这个:

template<>
struct ElementType<float, true> { ... };

template<>
struct ElementType<std::integral_constant<int, 0>, false> { ... };

现在您展开了它,您会看到第二个参数同时具有 true 和 false。您为每个选择专业化:

template<>
struct ElementType<float, true> { using Type = float; };

template<>
struct ElementType<std::integral_constant<int, 0>, false> {
    // int
    using Type = typename std::integral_constant<int, 0>::value_type;
};