std::array 的部分模板参数推导或解决方法?
Partial template argument deduction or workaround for std::array?
C++17 允许我们推导出 std::array
的模板参数。例如,我可以写
std::array ints = { 1, 2, 3 };
和 ints
将是 std::array<int, 3>
.
类型
我的问题是:如果我只想指定数组的类型参数但自动确定数组的大小怎么办?
以下内容不起作用,因为似乎必须指定所有模板参数:
std::array<size_t> sizes = { 1, 2, 3 };
我的编译器抱怨说:'std::array':模板参数太少。
是否可以通过模板参数推导自动确定数组的大小?如果不是,是否可以只指定类型而不指定大小来创建数组?
据我所知,这是做不到的。但是辅助方法可以解决问题:
template<typename Type, typename ... T>
constexpr auto makeArray(T&&... t) -> std::array<Type, sizeof...(T)>
{
return {{std::forward<T>(t)...}};
}
用法示例:
const auto container = makeArray<double>(-5.0, 0.0, 5.0, 10.0);
如果,我可能会大胆地扩展本杰明的答案。从概念上讲,不需要总是明确说明结果类型。
template<
typename ... T,
typename CT = std::common_type_t< T... >
>
constexpr auto make_array(T&& ... t)
-> std::array< CT , sizeof...(T)>
{
return { { static_cast<CT>( std::forward<T>(t) ) ...} };
}
用法稍微简单
constexpr auto std_arr = make_array(-5.0, 0.0, 5.0, 10.0);
这里的问题可能是,我们不能完全确定我们会得到什么类型的 std::array
。只要我们关心它。
const auto std_arr = make_array(-5.0, 0, 5.0, 10.0, 42.13f );
在 "here" 上,使用最新的 MSVC,我得到了标准双精度数组。如果一个人的睡前阅读是 ISO C++ 标准文档,那么他可能会确定 std::common_type
从正在使用的工具链中会产生什么类型。
对于我们其他人,文字后缀会有所帮助
constexpr auto sizes = make_array( 1UL, 2UL, 3UL );
但为什么要止于数字呢?可以将来自同一层次结构的实例快速收集到一个数组中。不关心结果类型。
{
const auto exceptions = make_array(
std::exception{"SE"},
std::runtime_error{"RE"},
std::logic_error{"LE"} );
}
有点无用但又有点奇怪和精彩。你要记住一件事:这是编译时的情况。因此,我可能更喜欢:
constexpr auto sizes = std::array{ 1UL, 2UL, 3UL } ;
直接回答OP的问题。
There is also C++20 std::to_array
。对于确切的结果类型和更舒适的用法:
constexpr auto sizes = std::to_array<size_t>({ 0, 1, 3 });
享受...
C++17 允许我们推导出 std::array
的模板参数。例如,我可以写
std::array ints = { 1, 2, 3 };
和 ints
将是 std::array<int, 3>
.
我的问题是:如果我只想指定数组的类型参数但自动确定数组的大小怎么办?
以下内容不起作用,因为似乎必须指定所有模板参数:
std::array<size_t> sizes = { 1, 2, 3 };
我的编译器抱怨说:'std::array':模板参数太少。
是否可以通过模板参数推导自动确定数组的大小?如果不是,是否可以只指定类型而不指定大小来创建数组?
据我所知,这是做不到的。但是辅助方法可以解决问题:
template<typename Type, typename ... T>
constexpr auto makeArray(T&&... t) -> std::array<Type, sizeof...(T)>
{
return {{std::forward<T>(t)...}};
}
用法示例:
const auto container = makeArray<double>(-5.0, 0.0, 5.0, 10.0);
如果,我可能会大胆地扩展本杰明的答案。从概念上讲,不需要总是明确说明结果类型。
template<
typename ... T,
typename CT = std::common_type_t< T... >
>
constexpr auto make_array(T&& ... t)
-> std::array< CT , sizeof...(T)>
{
return { { static_cast<CT>( std::forward<T>(t) ) ...} };
}
用法稍微简单
constexpr auto std_arr = make_array(-5.0, 0.0, 5.0, 10.0);
这里的问题可能是,我们不能完全确定我们会得到什么类型的 std::array
。只要我们关心它。
const auto std_arr = make_array(-5.0, 0, 5.0, 10.0, 42.13f );
在 "here" 上,使用最新的 MSVC,我得到了标准双精度数组。如果一个人的睡前阅读是 ISO C++ 标准文档,那么他可能会确定 std::common_type
从正在使用的工具链中会产生什么类型。
对于我们其他人,文字后缀会有所帮助
constexpr auto sizes = make_array( 1UL, 2UL, 3UL );
但为什么要止于数字呢?可以将来自同一层次结构的实例快速收集到一个数组中。不关心结果类型。
{
const auto exceptions = make_array(
std::exception{"SE"},
std::runtime_error{"RE"},
std::logic_error{"LE"} );
}
有点无用但又有点奇怪和精彩。你要记住一件事:这是编译时的情况。因此,我可能更喜欢:
constexpr auto sizes = std::array{ 1UL, 2UL, 3UL } ;
直接回答OP的问题。
There is also C++20 std::to_array
。对于确切的结果类型和更舒适的用法:
constexpr auto sizes = std::to_array<size_t>({ 0, 1, 3 });
享受...