代码之家  ›  专栏  ›  技术社区  ›  bartop

操作员MSVC错误|

  •  2
  • bartop  · 技术社区  · 8 年前

    我正在开发一个广泛使用C++模板的库。在编写时,我遇到了这样的代码(当然是简化的):

    #include <sstream>
    
    namespace ns{
        template<class A, class B>
        class c{};
    
        class a{};
    
        template<class A>
        class b{
        public:
            template<class B>
            auto
            take(A, B){
                return c<A, B>{};
            }
        };
    
        template<class A>
        auto
        make_b(A){
            return b<A>{};
        }
    
        template<class A, class B>
        auto
        operator|(A _a, B _b){
            return _b.take(_a, _b);
        }
    
    }
    
    using namespace ns;
    
    int main(){
        a{} | make_b(a{});
        return 0;
    }
    

    在使用msvc 19(Visual Studio 2017)编译时,我遇到了以下错误:

    /opt/compiler-explorer/windows/19.10.25017/lib/native/include/xlocale(314):警告C4530:使用了C++异常处理程序,但未启用展开语义。指定/EHsc (28):错误C2228:left of’。take必须具有类/结构/联合 (28):注:类型为“”

    /opt/compiler-explorer/windows/19.10.25017/lib/native/include/xstring(2923):注意:请参阅正在编译的函数模板实例化“auto-ns::operator |(A,B)”的参考 具有 [ A=无符号整数, B类= ] /opt/compiler-explorer/windows/19.10.25017/lib/native/include/xstring(2922):注意:在编译类模板成员函数的void std::basic\u string时,std::allocator>:SHINK\u to\u fit(void)'

    /opt/compiler-explorer/windows/19.10.25017/lib/native/include/system\u error(658):注意:请参阅函数模板实例化“void std::basic\u string,std::allocator”的参考:正在编译shrink\u to\u fit(void)'

    /opt/compiler-explorer/windows/19.10.25017/lib/native/include/stdexcept(22):注意:请参阅类模板实例化“std::basic\u string,std::allocator>”正在编译

    正在删除 using namespace 工作,但我不想禁止它(为什么我应该?)。有解决方案吗?

    编辑:当然,我用GCC和Clang测试了代码-从4.9和clang3在GCC下编译,所以这完全是MSVC的问题。

    EDIT2:我查看了报告的错误,似乎MSVC正在扩展过载的范围 operator| 使用时在其标准库中 使用命名空间 .

    1 回复  |  直到 8 年前
        1
  •  1
  •   Yola    8 年前

    它是这样工作的,但我无法解释为什么它不能以原来的方式工作,希望它能帮助其他人。

    虽然我猜你的模板是 太宽了 它由std库中的一些代码表示。实际上,如果您只需注释掉任何std头或删除 using namespace ns .

    namespace ns {
        template<class A, class B>
        class c {};
    
        class a {};
    
        template<class A>
        class b {
        public:
            using MyA = A;
            template<class B>
            auto
                take(A, B) {
                return c<A, B>{};
            }
        };
    
        template<class A>
        auto
            make_b(A) {
            return b<A>{};
        }
    
        template<class B>
        auto
            operator|(typename B::MyA _a, B _b) {
            return _b.take(_a, _b);
        }
    }