C++:为什么在#include <vector> 之前调用 std::wstring::begin() ?在此代码中导致编译器错误? [英] C++: why does calling std::wstring::begin() before #include <vector> cause a compiler error in this code?

查看:21
本文介绍了C++:为什么在#include <vector> 之前调用 std::wstring::begin() ?在此代码中导致编译器错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码:

#include <string>

void blah() {
    std::string str;
    str.begin();
}

#include <vector>

template <template <class...> class T, class U, class V, class ... Rest>
T<V> foo(const T<U, Rest...> &container, const V &arg) {
    (void)container;
    return T<V>({arg});
}

int main() {
    auto result = foo(std::vector<int>{1, 2, 3, 4, 5}, std::string("asdf"));
    return 0;
}

在使用 clang 编译时在第 17 行(调用 foo() 的行)产生以下错误:

produces the following error on line 17 (the line that calls foo()) when compiled with clang:

main.cpp:17:23: error: no matching function for call to 'foo'
        auto result = foo(std::vector<int>{1, 2, 3, 4, 5}, std::string("asdf"));
                      ^~~
main.cpp:11:10: note: candidate template ignored: substitution failure [with T = vector, U = int, V = std::__1::basic_string<char>, Rest = <std::__1::allocator<int>>]: too few template arguments for class template 'vector'
    T<V> foo(const T<U, Rest...> &container, const V &arg) {
    ~    ^

但是,如果我将 #include <vector> 移动到文件的顶部,错误就会消失.

However, if I move #include <vector> to the top of the file, the error goes away.

为什么会发生这种情况,有什么办法可以解决这个问题,同时 a) 保持这些 #include 语句的位置和 b) 不必重写 foo?

Why does this happen, and is there any way to work around it while a) maintaining the position of these #include statements and b) not having to rewrite foo?

这与我正在处理的库有关,因为它需要在定义调用 std::string::begin() 的内联函数的某些其他标头之前包含我的标头.如果可能的话,我想避免这种要求,特别是因为很可能有人会漫不经心地在我之前包含这些其他标头(因为通常不需要以特定顺序包含标头),从而导致此错误没有明显的修复.有问题的其他头文件"位于 Qt 的核心库中,包括 .

This is relevant to a library I'm working on, because it makes it necessary to include my header before certain other headers that define inline functions that call std::string::begin(). I'd like to avoid that requirement if at all possible, especially since it's quite likely someone might nonchalantly include these other headers before mine (as it's not usually necessary to include headers in a specific order), resulting in this error to which there's no obvious fix. The offending "other headers" are in Qt's core library, and include <QString>.

我的库需要定义函数,这些函数采用模板参数的数量不确定的模板模板参数,因此我使用了 template <class...>class T 以及为什么我不能重写 foo.

My library requires defining functions that take a template-template parameters with an uncertain number of template arguments, hence my usage of template <class...> class T and why I can't rewrite foo.

请注意,似乎有此问题的唯一 STL 类是 std::vector.如果我将第 17 行更改为使用 std::liststd::set 或其他 STL 容器类之一,则不会出现错误.

Note that the only STL class that seems to have this issue is std::vector. If I change line 17 to use std::list, std::set, or one of the other STL container classes, there's no error.

由于人们报告其他编译器没有抛出错误,我将补充说我的编译器是:macOS 10.11.6 上的 Apple LLVM 版本 8.0.0 (clang-800.0.42.1).

edit: Since people are reporting that other compilers aren't throwing an error, I'll add that my compiler is: Apple LLVM version 8.0.0 (clang-800.0.42.1) on macOS 10.11.6.

edit2:更新了示例代码以更接近我的实际用例.在此编辑之前 foo 没有返回值,但在我的库中它确实并且需要依赖默认模板参数,因此 @n.m. 提出的解决方案不幸的是对我没有帮助.

edit2: Updated the example code to more closely match my actual use case. Before this edit foo didn't return a value, but in my library it does and needs to rely on default template arguments, so the solution proposed by @n.m. unfortunately doesn't help me.

推荐答案

您可以像这样解决这个问题:

You can work around this issue like this:

template <template <class...> class T, class U, class ... Rest>
void foo(const T<U, Rest...> &container) {
   (void)container;
}

我不再确定这是编译器/库错误.或许情况正好相反(也就是说,编译器如果为原始代码发出诊断消息是错误的).标准的这一部分相当复杂,我不知道如何阅读.无论如何,提议的修复似乎是正确的.

I'm no longer sure it's a compiler/library bug. Perhaps the opposite is true (that is, compilers that do not emit a diagnostic message for the original code are in error). This part of the standard is rather convoluted and I'm not sure how to read it. The proposed fix seems to be correct regardless.

这篇关于C++:为什么在#include &lt;vector&gt; 之前调用 std::wstring::begin() ?在此代码中导致编译器错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆