偏特化模板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
的模板实例化扩展为 float
和 std::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;
};
我正在探索 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
的模板实例化扩展为 float
和 std::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;
};