是否有任何明显的方法可以重写此代码以解决触发无效 C2244 错误的编译器错误?

Is there any obvious way to rewrite this code to work around a compiler bug triggering invalid C2244 error?

提问人:Kuba hasn't forgotten Monica 提问时间:11/15/2023 最后编辑:Kuba hasn't forgotten Monica 更新时间:11/15/2023 访问量:78

问:

以下是 GCC 源代码库中符合标准的有效代码。它使Visual C++编译器跳闸,触发错误C2244。这是我已经报告过的编译器错误,但它不太可能很快得到解决。他们说影响太小了。现在,如果我的编译器产品在领先的开源编译器代码库上窒息,我会很生气,但这只是我。

是否有一些解决方法或方法可以重写它以保留 API,同时让它通过 VS C++?

在类声明中获取函数体可以解决这个问题,但这有点像风格上的噩梦,并且上游的可能性几乎为零。所以我希望能有不那么激烈的事情。

错误:

(17):错误 C2244:“hash_table::traverse_noresize”:无法将函数定义与现有声明匹配

下面的独立复制案例 - 也可在 Godbolt 上使用。不需要编译标志,AFAIK 它会绊倒 VS 2022 的所有版本。

// minimized excerpt from gcc/hash_table.h

template <class Descriptor> class hash_table
{
  using value_type = typename Descriptor::value_type;
public:
  template <int (*Callback)(value_type *)> void traverse_noresize ();
};

template<class Descriptor>
template<int (*Callback) (typename hash_table<Descriptor>::value_type *)>
void hash_table<Descriptor>::traverse_noresize() {}
// Error C2244 in line above. Apparently, this definition doesn't match the declaration
// in the class body.

struct D { using value_type = int; };
int C(int *slot) { return {}; }

void test()
{
    hash_table<D> ht;
    ht.traverse_noresize<C>();
}
C++ 可视化工作室 GCC

评论

1赞 Pepijn Kramer 11/15/2023
你是这个意思吗?godbolt.org/z/Wc67hz5Kh或者这不能解决您的问题吗?
0赞 Kuba hasn't forgotten Monica 11/15/2023
@PepijnKramer 不过,将这种相当侵入性的解决方法引入 gcc 代码库的可能性不大。

答:

4赞 ecatmur 11/15/2023 #1

问题是 MSVC 提前解析别名,然后在成员函数 (模板) 声明匹配期间无法解析它。在定义处手动消除锯齿似乎有效:hash_table<...>::value_type

template<typename Descriptor>
template<typename Argument,
     int (*Callback)
     (typename Descriptor::value_type *slot,
//             ^~~~~~~~~~
     Argument argument)>
void hash_table<Descriptor>::traverse_noresize () {}

演示

评论

0赞 Kuba hasn't forgotten Monica 11/15/2023
棒!谢谢!
0赞 Thomas Weller 11/15/2023
即使 Descriptor::value_type 是私有的,也有效?因为。。。private 仅用于动态多态性,而不是静态多态性?
0赞 Kuba hasn't forgotten Monica 11/15/2023
@ThomasWeller 它似乎适用于所有主要的编译器:)
1赞 Thomas Weller 11/15/2023
啊,不,我的错。该方法是类的一部分,因此可以看到私有内容。没事的。