Общее решение заключается в предоставлении специального конструктора для массивов (включается, когда T
является массивом), который копирует исходный массив в массив структуры.Это работает, но отбросить семантику перемещения для массивов.
#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;
}
live demo
Если вам нужно T
, чтобы иногда быть const
для не-массивов,улучшением будет определение value_type
как T
, если T
не является массивом, и std::remove_const_t<T>
в противном случае.