If I have the simple class written using c++20 concepts
#include <array>
#include <type_traits>
template <class T, int N>
struct MyVec {
std::array<T, N> m_vec;
template <typename... Q>
MyVec(Q&&... args)
requires (std::is_same_v<Q,T> && ...):
m_vec{std::forward<Q>(args)...} {}
};
and an example of it being used
int main(int argc, char* argv[]) {
using V = MyVec<double, 2>;
V v0(1., 2.);
V v1(1., 2.);
V v2 = v0;
}
The requires statement prevents the copy constructor from being hidden by the overly generic forwarding constructor. See https://godbolt.org/z/8Me19v7Ks
If you delete the requires statement then the line V v2 = v0
will fail to compile.
However I can't use concepts because this needs to be in a c++17 only context. I'm stuck trying to figure out how to use enable_if to protect the constructor. I could mark the construct as explicit but I'd prefer not to.
You can use enable_if
to disable the template:
template <class T, int N>
struct MyVec {
std::array<T, N> m_vec;
template <typename... Q,
std::enable_if_t<(std::is_convertible_v<Q, T> && ...), int> = 0>
MyVec(Q&&... args)
: m_vec{std::forward<Q>(args)...} {}
};
I am not an expert with concepts, but most (all?) of what you can do with requires
or similar, you can achieve with enable_if
, although it's usually a bit uglier (and error prone) and will lead to much less readable errors from compilers.