【问题标题】:C++20 non-type template parameter which is template in the prior type parameters: is not a valid template arg, because is not a variableC ++ 20非类型模板参数是先前类型参数中的模板:不是有效的模板参数,因为不是变量
【发布时间】:2020-11-02 23:40:02
【问题描述】:

我已经对此感到困惑了一段时间,并提炼了一个简单的错误消息示例。有什么方法可以使这项工作吗?我只是在某处缺少“模板”或“类型名”吗?

#include <cstdint>

template<typename T, typename J>
struct silly
{
    const void (*f)(T,J);
};

template<typename T, typename J, silly<T, J> aSilly>
struct sillier
{
    const uint32_t something;
};

void dumb_func(uint32_t i, uint32_t j)
{
    return;
}

constexpr silly<uint32_t, uint32_t> mySilly{ .f = dumb_func };

using silliest = sillier<uint32_t, uint32_t, mySilly>;

int main()
{
    return 2;
}

g++ 吐出:

g++ -std=c++2a ugh.cpp

ugh.cpp:20:51: error: invalid conversion from ‘void (*)(uint32_t, uint32_t)’ {aka ‘void (*)(unsigned int, unsigned int)’} to ‘const void (*)(unsigned int, unsigned int)’ [-fpermissive]
   20 | constexpr silly<uint32_t, uint32_t> mySilly{ .f = dumb_func };
      |                                                   ^~~~~~~~~
      |                                                   |
      |                                                   void (*)(uint32_t, uint32_t) {aka void (*)(unsigned int, unsigned int)}
ugh.cpp:20:51: error: ‘dumb_func’ is not a valid template argument of type ‘const void (*)(unsigned int, unsigned int)’ because ‘dumb_func’ is not a variable

我已尝试通读https://en.cppreference.com/w/cpp/language/template_parameters,但我在这里超出了我的模板深度。实际用例 T 和 J 类似于 std::array 然后 sillier> 继承自其他更通用的类,并覆盖 which call像 f 这样的函数,以便所有内容都内联到给定 silly 实例的专用函数中。

【问题讨论】:

  • 这与silly 是模板无关。
  • 有趣。但是由于删除最后一行解决了问题,它确实与它是一个非类型模板参数有关。
  • cdecl: explain const void (*f)(T,J); =&gt; declare f as pointer to function (T, J) returning const void ... explain void (* const f)(T,J); =&gt; declare f as const pointer to function (T, J) returning void -- const 应该在里面吗?
  • 是的,请参阅下面的 cmets。谢谢

标签: c++ templates c++20


【解决方案1】:

编辑:

sillier的第三个模板参数是非类型模板参数,只能绑定变量,但dumb_func不是变量。

这个解释没有意义,实际上代码可能没问题,错误可能只是在这个answer 中发现和报告的bug。但下面给出的修复仍然有效。


可以将第三个模板参数设为引用类型的非类型模板参数。

template<typename T, typename J, silly<T, J> const & aSilly>
                                          // ^^^^^^^
struct sillier
{
    const uint32_t something;
};

另外,silly 中的成员变量f 被声明为返回const void 类型的函数指针:

const void (*f)(T,J);

所以您要么需要从f 的返回类型中删除const,要么您可以更改dumb_func 的声明以返回const void 类型:

const void dumb_func(uint32_t i, uint32_t j)
{
    return;
}

const void 返回函数似乎没有任何意义,所以我会选择第一个选项。


这是demo

【讨论】:

  • >” 类型的东西,所以我没有注意关联性(或任何你称之为)的类型声明
  • @AlexanderSugar 没问题 :) 我明白你为什么现在这样做了。是的,将 const 放在正确的位置可能会很棘手,它总是让我感到困惑:p 试试 cdecl.org,它在这些情况下很有帮助。
  • 虽然我实际上仍然很困惑:你说第三个参数是一个非类型模板参数,所以我们不能将dumb_func绑定到它,但我并没有尝试绑定dumb_func,我正在尝试绑定mySilly,对吧?这也是我对错误消息感到困惑的地方......这与参数与参数有关吗?
  • @AlexanderSugar 好的,现在我什至不确定我的修复是否有必要。 clang 很高兴接受您的代码 :((在您修复 fconst 问题之后)。所以它可能是 gcc/clang 的错误。gcc 诊断有点奇怪。
  • @AlexanderSugar 啊,我明白了。 clang 11.0 不支持 :) 只需使用主干编译即可。
猜你喜欢
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-29
  • 2021-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多