我有一个设计,它触发了一个推断非类型模板参数的失败。我有以下最小的例子:
#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;
}
Playable example
由于超出这个最小示例范围的原因,我想对用于表示Mat
维数的类型进行微调。
然而,如果我不使用size_t
,DIM
就不能被推导出来,因为在调用点,它的类型是size_t
,而我的模板函数期望的是NbDim_t
,这是不同的,即使在编译时,编译器可以检测到转换是有效的。
1.模板推导的确切规则是什么,使这个设计错误(我找不到好的地方有template argument deduction rules)?
1.我如何修复这个设计(让NbDim_t
不是size_t
,并从std::array
参数推导出来)?
[编辑]我可能有第二部分的解决方案:
#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有更好的方法吗?
1条答案
按热度按时间kgsdhlau1#
非类型模板参数是从函数参数类型的模板参数列表中推导出来的,它必须具有完全相同的类型。来自cppreference上的链接文章www.example.com https://en.cppreference.com/w/cpp/language/template_argument_deduction#Deduction_from_a_type:
如果在函数参数的模板参数列表中使用函数模板的非类型模板参数(其也是模板),并且推导出相应的模板实参,则推导出的模板实参的类型(如在其封闭的模板参数列表中指定的,意味着保留引用)必须与非类型模板参数的类型完全匹配
或从标准[温度扣除类型] p20
如果
P
有一个包含<i>
的表单,并且如果i
的类型与由封闭的 * simple-template-id * 命名的模板的对应模板参数的类型不同,则演绎失败。下面给出这个例子:
所以,如果你想从
std::array<int, DIM>
推导出DIM
,DIM
* 必须 * 具有std::size_t
类型。您可以简单地让size_t隐式地转换为
NbDim_t
: