I have a design which triggers a failure to deduce a non-type template parameter. I have the following minimal example:
#include <array>
#include <cstdint>
// KO see below
// using NbDim_t = uint8_t;
using NbDim_t = size_t;
// let's say it's a N dimensionnal matrix
template <NbDim_t DIM>
struct Mat {
static constexpr NbDim_t dims = DIM;
};
// this is a matrix creator from an array of size of it's different dimensions
template <NbDim_t DIM>
Mat<DIM> Create(std::array<int, DIM> input) {
return Mat<DIM>();
}
int main() {
std::array<int, 3> d = {1, 2, 3};
// KO if NbDim_t si not std::array<whatever,whatever>::size_type
// cannot deduced a non-type template parameter of one type from a value of
// different type
auto M = Create(d);
return 0;
}
For reasons beyond the scope of this minimal example, I'd like to fine-tune the type used to represent the number of dimensions of my Mat
.
Yet if I don't use size_t
, DIM
cannot be deduced because, at the calling point, it is of type size_t
and my template function is expecting NbDim_t
which is different, even if, at compile-time, the compiler could detect that the conversion would be valid.
- What is the exact rule of template deduction that make this design erroneous (I can't find the good spot there template argument deduction rules)?
- How can I fix this design (to have
NbDim_t
not asize_t
and deduced from thestd::array
argument)?
[EDIT] I may have a solution for part 2:
#include <array>
#include <cstddef>
#include <cstdint>
// OK now
using NbDim_t = uint8_t;
// using NbDim_t = size_t;
// let's say it's a N dimensionnal matrix
template <NbDim_t DIM>
struct Mat {
static constexpr NbDim_t dims = DIM;
};
// this is a matrix creator from an array of size of it's different dimensions
template <size_t N, NbDim_t DIM = N>
Mat<DIM> Create(std::array<int, N> input) {
return Mat<DIM>();
}
int main() {
std::array<int, 3> d = {1, 2, 3};
// N deduced then set into DIM
auto M = Create(d);
return 0;
}
Live Is there a better way to do that?