使用全局 std::array 引用作为模板参数时如何简化参数?



这在第 17 C++中有效:

template <std::size_t N, const std::array<int, N> & ARRAY> class Foo {};
constexpr std::array<int, 3> A{1, 2, 3};
void bar()
{
Foo<3, A> foo_a;
}

那么有没有办法避免在Foo的模板参数中写入N呢?因为我们可以很容易地从ARRAY.size()中知道它.我试过这个,失败了:

template <template <size_t N> const std::array<int, N> & ARRAY> Foo {}; // Error.

无需指定引用的确切类型。您可以使用占位符:

#include<array>
template <auto& ARRAY> class Foo {
static constexpr auto N = ARRAY.size();
};
constexpr std::array<int, 3> A{1, 2, 3};
void bar()
{
Foo<A> foo_a;
}

如果你想在模板参数不是对std::array<int, ...>的引用时得到错误,你可以编写一个类型特征,告诉你该类型是否是std::array的实例化,并检查value_type

#include<array>
#include<type_traits>
template<typename>
struct is_std_array : std::false_type {};
template<typename T, std::size_t N>
struct is_std_array<std::array<T, N>> : std::true_type {};
template<typename T>
inline constexpr auto is_std_array_v = is_std_array<T>::value;
// std::remove_cvref_t will be part of C++20
template<typename T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
template<auto& ARRAY>
class Foo {
using ARRAY_type = remove_cvref_t<decltype(ARRAY)>;
static_assert(is_std_array_v<ARRAY_type>,
"Foo requires reference to std::array of int as template argument!");
static_assert(std::is_same_v<typename ARRAY_type::value_type, int>,
"Foo requires reference to std::array of int as template argument!");
constexpr static auto N = ARRAY.size();
};
constexpr std::array<int, 3> A{1, 2, 3};
constexpr std::array<long, 3> B{1, 2, 3};
constexpr int C = 5;
void bar()
{
Foo<A> foo_a;
// Foo<B> foo_b; // Will give static_assert error message
// Foo<C> foo_c; // Will give static_assert error message
}

在 C++20 中将有一些概念,这将允许您编写一个概念来测试我现在正在使用static_asserts 测试的属性,您将能够使用该概念代替模板参数中的auto

通过部分专业化的可能解决方案

template <auto const &>
class Foo;
template <std::size_t N, std::array<int, N> const & ARRAY>
class Foo<ARRAY>
{ };

所以你可以写

constexpr std::array<int, 3> A{1, 2, 3};
int main ()
{
Foo<A> foo_a;
}

最新更新