假设我们有一些模板化结构,有时它的模板应该是一个数组。如何在struct中初始化数组?
此
template<typename T>
struct A {
T x;
A(T x) : x(x) {}
};
int a[6];
A<decltype(a)> b(a);
在编译期间生成错误:
error: array initializer must be an initializer list
A(T x) : x(x) {}
^
UPD1。此内容使用的代码更完整:
template<typename T>
struct A {
T x;
A(const T& x) : x(x) {}
A(const T&& x) : x(std::move(x)) {}
};
template<typename T>
A<typename std::remove_reference<T>::type> make_A(T&& a) {
return A<typename std::remove_reference<T>::type>(std::forward<T>(a));
}
auto a = make_A("abacaba");
答案 0 :(得分:4)
一般的解决方案是为数组提供一个特殊的构造函数(当T
是一个数组时启用),它将源数组复制到struct的数组中。它可以工作,但丢弃数组的移动语义。
#include <iostream>
#include <type_traits>
#include <string>
#include <tuple>
template<typename T>
struct A {
using value_type = std::remove_const_t<T>;
value_type x;
template<class U=T> A(const T& src, std::enable_if_t<!std::is_array_v<U>, int> = 0) : x(src) {}
template<class U=T> A(const T&& src, std::enable_if_t<!std::is_array_v<U>, int> = 0) : x(std::move(src)) {}
template<class U=T> A(const T& src, std::enable_if_t< std::is_array_v<U>, int> = 0) { std::copy(std::begin(src), std::end(src), std::begin(x)); }
};
template<typename T>
auto make_A(T&& a)
{ return A<typename std::remove_reference_t<T>>(std::forward<T>(a)); }
int main()
{
auto a1 = make_A("the answer");
std::ignore = a1;
auto a2 = make_A(42);
std::ignore = a2;
}
如果有时需要T
const
为非数组,如果value_type
不是T
,则T
定义为std::remove_const_t<T>
数组,否则为 if (this.props.dataState.loaded){
data = this.props.data.content;
} else {
this.renderLoading();
}
return( ...
。
答案 1 :(得分:1)
我建议将所有智能放入make_A
,将C阵列转换为std::array<>
,以便A<>
只需要使用常规类型:
namespace detail {
template<typename T, std::size_t... Is>
constexpr std::array<T, sizeof...(Is)> to_std_array(T const* const p,
std::index_sequence<Is...>)
{
return {{p[Is]...}};
}
}
template<typename T>
A<std::decay_t<T>> make_A(T&& x) {
return {std::forward<T>(x)};
}
template<typename T, std::size_t N>
A<std::array<T, N>> make_A(T const (& x)[N]) {
return {detail::to_std_array(x, std::make_index_sequence<N>{})};
}
的 Online Demo 强>
如果您特别关注硬编码的C字符串(通常与C阵列相反),请考虑转换为string_view
类型而不是std::array<>
以节省一些空间。
答案 2 :(得分:0)
如果您想要专门为C-Strings实现特殊行为,您可以添加一种特殊处理:
{{1}}
答案 3 :(得分:-1)
使用 std :: decay 它可以工作:
template<typename T>
A<typename std::decay<T>::type> make_A(T&& a) {
return A<typename std::decay<T>::type>(std::forward<T>(a));
}