c++ 无法从不同类型的值推导出非类型模板参数

9w11ddsr  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(175)

我有一个设计,它触发了一个推断非类型模板参数的失败。我有以下最小的例子:

  1. #include <array>
  2. #include <cstdint>
  3. // KO see below
  4. // using NbDim_t = uint8_t;
  5. using NbDim_t = size_t;
  6. // let's say it's a N dimensionnal matrix
  7. template <NbDim_t DIM>
  8. struct Mat {
  9. static constexpr NbDim_t dims = DIM;
  10. };
  11. // this is a matrix creator from an array of size of it's different dimensions
  12. template <NbDim_t DIM>
  13. Mat<DIM> Create(std::array<int, DIM> input) {
  14. return Mat<DIM>();
  15. }
  16. int main() {
  17. std::array<int, 3> d = {1, 2, 3};
  18. // KO if NbDim_t si not std::array<whatever,whatever>::size_type
  19. // cannot deduced a non-type template parameter of one type from a value of
  20. // different type
  21. auto M = Create(d);
  22. return 0;
  23. }

Playable example
由于超出这个最小示例范围的原因,我想对用于表示Mat维数的类型进行微调。
然而,如果我不使用size_tDIM就不能被推导出来,因为在调用点,它的类型是size_t,而我的模板函数期望的是NbDim_t,这是不同的,即使在编译时,编译器可以检测到转换是有效的。
1.模板推导的确切规则是什么,使这个设计错误(我找不到好的地方有template argument deduction rules)?
1.我如何修复这个设计(让NbDim_t不是size_t,并从std::array参数推导出来)?
[编辑]我可能有第二部分的解决方案:

  1. #include <array>
  2. #include <cstddef>
  3. #include <cstdint>
  4. // OK now
  5. using NbDim_t = uint8_t;
  6. // using NbDim_t = size_t;
  7. // let's say it's a N dimensionnal matrix
  8. template <NbDim_t DIM>
  9. struct Mat {
  10. static constexpr NbDim_t dims = DIM;
  11. };
  12. // this is a matrix creator from an array of size of it's different dimensions
  13. template <size_t N, NbDim_t DIM = N>
  14. Mat<DIM> Create(std::array<int, N> input) {
  15. return Mat<DIM>();
  16. }
  17. int main() {
  18. std::array<int, 3> d = {1, 2, 3};
  19. // N deduced then set into DIM
  20. auto M = Create(d);
  21. return 0;
  22. }

Live有更好的方法吗?

kgsdhlau

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 * 命名的模板的对应模板参数的类型不同,则演绎失败。
下面给出这个例子:

  1. template<int i> class A { /* ... */ };
  2. template<short s> void f(A<s>);
  3. void k1() {
  4. A<1> a;
  5. f(a); // error: deduction fails for conversion from int to short
  6. f<1>(a); // OK
  7. }

所以,如果你想从std::array<int, DIM>推导出DIMDIM * 必须 * 具有std::size_t类型。
您可以简单地让size_t隐式地转换为NbDim_t

  1. template <std::size_t DIM>
  2. Mat<DIM> Create(std::array<int, DIM> input) {
  3. return Mat<DIM>();
  4. }
展开查看全部

相关问题