Что мешает форме Boost.Format использовать перегрузку моего оператора потока для необязательного int? - PullRequest
0 голосов
/ 26 ноября 2018

Я хочу использовать 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.

1 Ответ

0 голосов
/ 26 ноября 2018

boost::format("%s") % i вызывает вызов operator<<.Во время компиляции соблюдается правило поиска имени, чтобы найти operator<<.

. Для boost::format("%s") % t и struct SomeType, и std::ostream& operator<<(std::ostream& os, const SomeType& t) определены в глобальном пространстве имен, с помощью ADL найден operator<<.

Для (boost::format("%s") % i), std::optional определено в пространстве имен std, но соответствующее operator<< определено в глобальном пространстве имен.Используя ADL, boost не сможет его найти.И

поиск без ADL проверяет объявления функций с внешними связями, которые видны из контекста определения шаблона,

, поэтому компилятор не может найти operator<< который вы определили.

Обходной путь: wrap std :: необязательный внутри вашего собственного ReferenceWrapper, затем определите вставщик для вашей оболочки в том же пространстве имен, где определен ReferenceWrapper.

...