有没有在世界C ++的,这将使我想要做什么可能?
template < typename T
, size_t Size >
struct array
{
constexpr T buf[Size];
constexpr size_t size() const { return Size; }
};
template < typename T
, size_t Size >
constexpr array<T,Size+1> push_back(array<T,Size> const& arr, T const& val)
{
array<T,Size+1> arr_out = {{arr.buf, val}};
return arr_out;
}
我正在试图做的是建立与其他的数据初始化的新阵列,并提出了新的元素结束。
减去constexpr我可以得到它通过循环中的push_back函数初始化工作。 看来你不能这样做,在constexpr功能,这有一定道理,虽然我觉得一个足够聪明的编译器可以明白这一点。
我敢肯定它不能这样做,但我很乐意被显示错误。
指数招 ,耶〜
template < typename T
, size_t Size >
struct array
{
T buf[Size]; // non-static data members can't be constexpr
constexpr size_t size() const { return Size; }
};
namespace detail{
template< typename T, size_t N, size_t... Is>
constexpr array<T, N+1> push_back(array<T, N> const& arr, T const& val, indices<Is...>)
{
// can only do single return statement in constexpr
return {{arr.buf[Is]..., val}};
}
} // detail::
template < typename T, size_t Size >
constexpr array<T,Size+1> push_back(array<T,Size> const& arr, T const& val)
{
return detail::push_back(arr, val, build_indices<Size>{});
}
活生生的例子。
扩大对XEO的答案,这里是转发其参数的版本:
#include <boost/mpl/if.hpp>
#include <cstddef>
#include <utility>
#include <iostream>
template<typename T, std::size_t Size>
struct array
{
typedef T value_type;
T buf[Size];
constexpr std::size_t size() const { return Size; }
};
template<typename T>
struct array_size;
template<typename T, std::size_t Size>
struct array_size<array<T, Size>> {
static constexpr std::size_t value = Size;
};
template <typename T>
using Bare =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template <typename T>
constexpr T&& forward(typename std::remove_reference<T>::type& t) noexcept {
return static_cast<T&&>(t);
}
template<typename Array>
using CVValueType = typename boost::mpl::if_<
std::is_const<Array>,
typename boost::mpl::if_<
std::is_volatile<Array>,
typename Array::value_type const volatile,
typename Array::value_type const>::type,
typename boost::mpl::if_<
std::is_volatile<Array>,
typename Array::value_type volatile,
typename Array::value_type>::type
>::type;
template<typename Array>
using ForwardType =
typename boost::mpl::if_c<
std::is_lvalue_reference<Array>::value,
CVValueType<typename std::remove_reference<Array>::type>&,
CVValueType<typename std::remove_reference<Array>::type>&&>::type;
template <typename Array>
constexpr ForwardType<Array> forward_element(
CVValueType<typename std::remove_reference<Array>::type>& t) noexcept
{
return static_cast<ForwardType<Array>>(t);
}
template <std::size_t... Is>
struct indices {};
template <std::size_t N, std::size_t... Is>
struct build_indices
: build_indices<N-1, N-1, Is...> {};
template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};
template<typename Array>
using Enlarged =
array<typename Bare<Array>::value_type, array_size<Bare<Array>>::value+1>;
template<typename Array, typename T, std::size_t... Is>
constexpr Enlarged<Array> push_back(Array&& arr, T&& val, indices<Is...>)
{
return {{forward_element<Array>(arr.buf[Is])..., forward<T>(val)}};
}
template <typename Array, typename T>
constexpr Enlarged<Array> push_back(Array&& arr, T&& val)
{
return push_back(
forward<Array>(arr),
forward<T>(val),
build_indices<array_size<Bare<Array>>::value>{});
}
namespace detail_
{
template < typename T
, size_t End >
struct push_backer
{
template < typename Array
, typename ... Args>
static constexpr auto push_back(Array const& arr, Args const& ... args) -> decltype(push_backer<T,End-1>::push_back(arr, arr.buf[End-1],args...))
{
return push_backer<T,End-1>::push_back(arr, arr.buf[End-1], args...);
}
};
template < typename T >
struct push_backer<T,0>
{
template < size_t Size
, typename ... Args>
static constexpr array<T,Size+1> push_back(array<T,Size> const& arr, Args const& ... args)
{
return array<T,Size+1>{{args...}};
}
};
}
template < typename T
, size_t Size >
constexpr array<T,Size+1> push_back(array<T,Size> const& arr, T const& val)
{
return detail_::push_backer<T,Size>::push_back(arr, val);
}