using 命名空间指令是否使名称在内联函数中可用?

问题描述 投票:0回答:1

考虑声明一个不受约束的

ns::operator*
。在块作用域中的
using namespace ns
并调用函数
foo<T>
之后,clang 在读取
ns::operator*
内基于范围的循环的迭代器时使用
foo
。不涉及
ns
中的其他类型,因此 ADL 应该不会产生候选者。

在以下示例中,

static_assert
失败并显示消息:

错误:静态断言由于要求“std::is_same_v”而失败

汇编代码显示

ns::operator*
是由clang使用的。 gcc 和 msvc 的断言都通过了!

namespace ns {

template <typename T>
constexpr auto operator*(T&& /*value*/) {
    struct custom_type {};
    return custom_type{};
};

}  // namespace ns

template <typename T>
constexpr void foo() {
    std::vector<T> vec{};
    for (const auto& curr : vec) {
        static_assert(std::is_same_v<const T&, decltype(curr)>);
    }
}

int main() {
    using namespace ns;
    foo<int>();
}

这是一个 godbolt 链接:https://godbolt.org/z/z5vf48Mda

我无法通过手动调用

operator*
内的
foo
来重现问题。此外,当
foo
未模板化 不是
constexpr
时,断言将通过 clang。这就好像 clang 内联
foo<T>
一样,因此将
ns::operator*
视为有效的候选者。我几乎可以肯定 clang 已损坏,因为该问题仅在使用基于范围的循环时出现。

clang 或 gcc/msvc 是否正确,或者我们正在处理未指定/未定义的行为?

c++ templates namespaces using
1个回答
0
投票

Clang 似乎有一个错误。

using namespace ns
中的
main
不应该对
foo
中的查找产生任何影响,并且通过任何形式的查找都不可能在
ns::operator*
中找到
foo

如果未声明

foo
,Clang 不会产生此行为
constexpr
,尽管这应该不会对名称查找产生任何影响。

如果将 range-for 循环替换为等效的简单循环结构,也不会产生此行为。

这向我表明,在 range-for 循环中如何处理查找存在一个错误。

© www.soinside.com 2019 - 2024. All rights reserved.