我不想创建一个非常小的数学库,它对 constexpr 有很好的支持。
为了简化问题,我们在这里只讨论向量。
template <typename T, unsigned int N> struct vec {
std::array<T, N> m_data;
};
typedef vec<float, 2> vec2;
现在我想为 vec 结构创建一个构造函数,它应该如下所示。
constexpr vec2 x = vec2(1.0f, 2.0f);
// or even nicer but probably not possible
constexpr vec2 y = {1.0f, 2.0f};
我更喜欢第二个例子,因为它也可以更好地构造矩阵,但我不认为在 c++17 中可以在不丢失 const 评估的情况下实现这一点,因为它可能需要 initalizer_lists,而 initalizer_lists 不是就我现在而言,consteval 因为它们具有动态范围。
但即使有了第一个例子,我也不知道如何实现这个 我发现了这个线程,它提出了。
template <std::size_t N>
struct foobar
{
template <typename ...Args, typename = typename std::enable_if<N == sizeof...(Args), void>::type>
foobar(Args&&... args) { ... }
};
看起来很有前途(在 array.h 标头中使用了类似的语法),
template<typename _Tp, typename... _Up>
array(_Tp, _Up...)
-> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
1 + sizeof...(_Up)>;
这里的问题是两者都没有声明为 constexpr。如果有人有任何想法如何将其实现为 constexpr 构造函数。此外,这两种情况下主体都丢失了,我仍然没有弄清楚如何从参数包创建数组。
请不要抱怨 T 不受我正在研究的概念的限制,作为澄清,如果这里有任何其他选项,它不必使用 std::array 我非常开放任何建议.
找到解决办法了
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))...}}) {}
}
看起来效果不错