0

我希望能够使用std::optional<int>Boost.Format。

#include <iostream>
#include <optional>
#include <boost/format.hpp>

struct SomeType
{
    int x;
};

std::ostream& operator<<(std::ostream& os, const SomeType& t)  
{
    os << t.x;
    return os;
}

std::ostream& operator<<(std::ostream& os, const std::optional<int>& t)  
{
    os << t.value_or(0);
    return os;
}

void test()
{
    SomeType t{42};
    std::cout << (boost::format("%s") % t); //this is fine
    std::optional<int> i = 42;
    std::cout << (boost::format("%s") % i); //nope
}

上面的代码给了我以下编译器错误:

opt/compiler-explorer/libs/boost_1_68_0/boost/format/feed_args.hpp:99:12: error: no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'const std::optional<int>')
    os << x ;
    ~~~^~~~

如果我只是i直接传递给std::cout.

4

1 回答 1

2

boost::format("%s") % i调用operator<<. 在编译期间遵循名称查找规则以查找operator<<.

对于boost::format("%s") % t, structSomeTypestd::ostream& operator<<(std::ostream& os, const SomeType& t)都是在全局命名空间中定义的,通过使用 ADL,operator<<找到了。

对于(boost::format("%s") % i),std::optional是在命名空间中定义的std,但对应operator<<的是在全局命名空间中定义的。通过使用 ADL,boost 将无法找到它。和

非 ADL 查找检查具有从模板定义上下文可见的外部链接的函数声明,

所以编译器无法找到operator<<您定义的。

解决方法:将 std::optional 包装在您自己的 ReferenceWrapper 中,然后在定义 ReferenceWrapper 的同一命名空间中为您的包装器定义插入器。

于 2018-11-26T10:00:06.020 回答