代码之家  ›  专栏  ›  技术社区  ›  Kuba hasn't forgotten Monica

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

  •  3
  • Kuba hasn't forgotten Monica  · 技术社区  · 2 年前

    以下是有效的、符合标准的代码 from the GCC source code base 。它会触发Visual C++编译器,从而触发错误C2244。 That is a compiler bug that I already reported, but it's unlikely to get solved soon 。他们说影响太小了。 现在,如果我的编译器产品被一个领先的开源编译器代码库卡住了,我会很生气,但那只是我自己。

    是否有一些变通方法或方法来重写它,以在使API通过VS C++的同时保留它?

    将函数体放入类声明中可以解决这个问题,但这有点像风格上的噩梦,并且几乎没有机会进行上游处理。所以我希望有一些不那么激烈的事情。

    错误:

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

    下面是独立的repro case-也可提供 on 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>();
    }
    
    1 回复  |  直到 2 年前
        1
  •  4
  •   ecatmur    2 年前

    问题是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 () {}
    

    Demo