【问题标题】:MSVC error with operator |操作员的 MSVC 错误 |
【发布时间】:2018-07-13 19:58:38
【问题描述】:

我正在开发一个广泛使用 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: '.take' 的左边必须有类/结构/联合 (28): 注意:类型是''

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

/opt/compiler-explorer/windows/19.10.25017/lib/native/include/system_error(658):注意:参见函数模板实例化'void std::basic_string,std::allocator>::shrink_to_fit (void)' 正在编译

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

删除using namespace 有效,但我不想禁止它(我为什么要禁止它?)。有解决办法吗?

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

EDIT2:我查看了报告的错误,似乎 MSVC 在使用 using namespace 时在其标准库中扩展了重载 operator| 的范围。

【问题讨论】:

  • A) 如果它不能编译,也许你不是在问优化? B) 也许您想发布实际的错误消息?
  • 抱歉,已编辑评论,`couse 犯了一个错误。
  • 刚刚在godbolt 上查看了您的代码,您错过了第一条错误消息,请将其包含在您的帖子中。

标签: c++ templates visual-c++


【解决方案1】:

它以这种方式工作,但我无法解释为什么它不能以原始方式工作,希望对其他人有所帮助。

虽然我的猜测是您的模板过于宽泛,并且它会被 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);
    }
}

【讨论】:

  • 我必须说这很有趣。你刚刚添加了这个using MyA = A
  • @bartop 是的,就是这样
  • 我猜这个模板不太宽泛,因为 gcc 和 clang 接受它。更像是 msvc 在它的库中做了一些肮脏的事情,假设没有人会做我做过的事情。
猜你喜欢
  • 1970-01-01
  • 2015-04-13
  • 1970-01-01
  • 1970-01-01
  • 2011-10-29
  • 2012-06-18
  • 2012-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多