Cxx-prettyprint(用于标准容器)在命名空间std中定义了它的输出操作符——这违反了标准吗?

Cxx-prettyprint (for standard containers) defines its output operators inside namespace std - is this a standard violation?

本文关键字:标准 操作符 输出 定义 用于 std 命名空间 Cxx-prettyprint      更新时间:2023-10-16

我已经成功地使用cxx-prettyprint: A c++ Container Pretty-Printer来记录容器值。(另见Pretty-print c++ STL容器)即使在旧的VS-2005 (VC8)编译器上(带有prettyprint98.hpp头),它也能很好地在VS2017-2019上工作,例如在单元测试中使容器值可打印。

在研究它与Boost的互操作性时。格式,我惊讶地发现,当其他问题认为它不应该,因为ADL应该失败的用户提供的输出操作符。

查看cxx-pp头文件,我发现它可以正常工作,因为库确实在 中定义了它的输出操作符 std命名空间:
// Main magic entry point: An overload snuck into namespace std.
// Can we do better?
namespace std
{
    // Prints a container to the stream using default delimiters
    template<typename T, typename TChar, typename TCharTraits>
    inline typename enable_if< ::pretty_print::is_container<T>::value,
                              basic_ostream<TChar, TCharTraits> &>::type
    operator<<(basic_ostream<TChar, TCharTraits> & stream, const T & container)
    {
        return stream << ::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
    }
}    
....

显然,作者并不是100%确信:qq "我们能做得更好吗? "

std命名空间添加内容的形式为UB:

[C++11: 17.6.4.2.1/1]:如果一个c++程序向命名空间std或命名空间std中的命名空间添加声明或定义,除非另有说明,否则该程序的行为是未定义的。程序可以将任何标准库模板的模板专门化添加到命名空间std,前提是声明依赖于用户定义的类型,并且专门化满足原始模板的标准库要求,并且没有明确禁止。

那么,这在cxx-pp中是正式的UB,还是模板专门化(对我来说似乎不是)。

这由[namespace]覆盖。标准中的Std]/1(在问题中引用,但在这里复制它,因为它也是答案):

c++程序的行为是未定义的,如果它向命名空间std或命名空间std中的命名空间添加声明或定义,除非另有说明。

对于新的用户定义类型的operator<<重载没有任何"其他指定"。

所以行为是未定义的(不需要诊断)。

在实际中,看起来代码要么工作要么不工作,但与所有UB一样,我们应该小心不要排除任何其他可能性。