I want to create a very small math library, which has good support for constexpr
.
To simplify the problem, let's just talk about vectors here:
template <typename T, unsigned int N> struct vec {
std::array<T, N> m_data;
};
typedef vec<float, 2> vec2;
Now, I want to create a constructor for the vec
struct, which should look like this:
constexpr vec2 x = vec2(1.0f, 2.0f);
// or even nicer but probably not possible
constexpr vec2 y = {1.0f, 2.0f};
I would like the second example more, because it would allow for better construction of matricies as well, but I don't believe that's possible in C++17 without losing the const
evaluation, because it might require initializer_list
s, which are not consteval
, as far as I know, because they have a dynamic range.
But even with the first example, I'm not sure how to implement this.
I found this thread, which proposes:
template <std::size_t N>
struct foobar
{
template <typename ...Args, typename = typename std::enable_if<N == sizeof...(Args), void>::type>
foobar(Args&&... args) { ... }
};
Which looks promising (a similar syntax is used in the array.h
header):
template<typename _Tp, typename... _Up>
array(_Tp, _Up...)
-> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
1 + sizeof...(_Up)>;
The problem here is that both are not declared constexpr
.
Does anybody have any ideas how to implement this as a constexpr
constructor? Additionally, the body is missing in both cases, and I still haven't figured out how to create an array from a parameter pack.
Please don't complain about T
not being constrained by a concept
. I'm working on it, and as a clarification it doesn't have to use std::array
if there are any other options here. I'm very open to any suggestion.
Found a solution
template <typename T, size_t N> struct vec {
template <typename... E,
typename = typename std::enable_if_t<
std::conjunction_v<std::is_convertible<E, T>...> &&
N == (1 + sizeof...(E)),
void>>
constexpr explicit vec(
T v, E &&...elements) noexcept
: m_elements({{v, static_cast<float>(std::forward<E>(elements))...}}) {}
}
Seems to work fine