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_tnot asize_tand deduced from thestd::arrayargument)?
[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?
A non-type template parameter is deduced from the template argument list of the type of a function parameter, it must have the exact same type. From the linked article on cppreference https://en.cppreference.com/w/cpp/language/template_argument_deduction#Deduction_from_a_type:
Or from the standard [temp.deduct.type]p20
With this example given:
So, if you want
DIMto be deduced fromstd::array<int, DIM>,DIMmust have the typestd::size_t.You can simply let the size_t implicitly convert to
NbDim_t: