Jo *_*tes 7 c++ arrays variadic-templates c++11
在我使用的所有现代C++编译器中,以下是合法的:
std::array<float, 4> a = {1, 2, 3, 4};
Run Code Online (Sandbox Code Playgroud)
我正在尝试创建具有类似构造语义的我自己的类,但我遇到了一个恼人的问题.考虑以下尝试:
#include <array>
#include <cstddef>
template<std::size_t n>
class float_vec
{
private:
std::array<float, n> underlying_array;
public:
template<typename... Types>
float_vec(Types... args)
: underlying_array{{args...}}
{
}
};
int main()
{
float_vec<4> v = {1, 2, 3, 4}; // error here
}
Run Code Online (Sandbox Code Playgroud)
当使用上面的int文字时,编译器会抱怨它无法隐式转换int为float.我认为它在这个std::array例子中起作用,因为给出的值是已知属于域内的编译时常量float.另一方面,可变参数模板int用于参数类型,转换发生在构造函数的初始化列表中,其中值在编译时是未知的.
我不想在构造函数中进行显式强制转换,因为这样就可以允许所有数值,即使它们不能表示float.
我能想到得到我想要的唯一方法是以某种方式具有可变数量的参数,但具有特定类型(在这种情况下,我想要float).我知道std::initializer_list,但我希望能够在编译时强制执行参数的数量.
有任何想法吗?我想要的C++ 11甚至可能吗?为C++ 14提出的任何新建议都能解决这个问题吗?
小智 5
一个小技巧是使用构造函数继承。只需让您的类派生自另一个具有您想要的参数包的类。
template <class T, std::size_t N, class Seq = repeat_types<N, T>>
struct _array_impl;
template <class T, std::size_t N, class... Seq>
struct _array_impl<T, N, type_sequence<Seq...>>
{
_array_impl(Seq... elements) : _data{elements...} {}
const T& operator[](std::size_t i) const { return _data[i]; }
T _data[N];
};
template <class T, std::size_t N>
struct array : _array_impl<T, N>
{
using _array_impl<T, N>::_array_impl;
};
int main() {
array<float, 4> a {1, 2, 3, 4};
for (int i = 0; i < 4; i++)
std::cout << a[i] << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是repeat_types 实用程序的示例实现。此示例使用对数模板递归,与线性递归相比,实现起来不太直观。
template <class... T>
struct type_sequence
{
static constexpr inline std::size_t size() noexcept { return sizeof...(T); }
};
template <class, class>
struct _concatenate_sequences_impl;
template <class... T, class... U>
struct _concatenate_sequences_impl<type_sequence<T...>, type_sequence<U...>>
{ using type = type_sequence<T..., U...>; };
template <class T, class U>
using concatenate_sequences = typename _concatenate_sequences_impl<T, U>::type;
template <std::size_t N, class T>
struct _repeat_sequence_impl
{ using type = concatenate_sequences<
typename _repeat_sequence_impl<N/2, T>::type,
typename _repeat_sequence_impl<N - N/2, T>::type>; };
template <class T>
struct _repeat_sequence_impl<1, T>
{ using type = T; };
template <class... T>
struct _repeat_sequence_impl<0, type_sequence<T...>>
{ using type = type_sequence<>; };
template <std::size_t N, class... T>
using repeat_types = typename _repeat_sequence_impl<N, type_sequence<T...>>::type;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
859 次 |
| 最近记录: |