Принцип, который вы пытаетесь использовать, называется Argument Dependent Lookup .Если у меня есть функция и тип, объявленные в одном и том же пространстве имен, я могу использовать их вместе вне пространства имен без необходимости указывать, из какого пространства имен функция:
//In MyClass.h
namespace foo {
class MyClass { /* stuff */ };
}
//In doStuff.h
namespace foo {
void doStuff(MyClass c) { /* stuff */ }
}
//in main.cc
int main() {
foo::MyClass tom; //I'm bad with names
doStuff(tom); //Here, we don't have to specify the namespace
}
Это почти что происходит в вашем примере.Разница в том, что halfseconds
фактически не объявлено в пространстве имен lib
.Поскольку halfseconds
является псевдонимом, он фактически объявлен в std::chrono
, и когда вы помещаете перегрузку operator<<
в пространство имен lib
, компилятор не проверяет его.
Как это исправить
Самый простой способ это исправить - объявить новый тип в пространстве имен lib:
// lib/halfseconds.h:
#include <chrono>
namespace lib {
class halfseconds
: public std::chrono::duration<intmax_t, std::ratio<1, 2>>
{
public:
using Base = std::chrono::duration<intmax_t, std::ratio<1, 2>>;
using Base::Base; //Use the constructor
};
}
// lib/debug.h:
#include <ostream>
namespace lib {
std::ostream& operator<<(std::ostream& o, lib::halfseconds halves)
{
double seconds = halves.count();
seconds /= lib::halfseconds::period::den;
o << seconds << 's';
return o;
}
}
// demo/main.cpp:
#include <iostream>
int main()
{
lib::halfseconds threeHalvseconds(3);
std::cout << threeHalvseconds << '\n'; // 1.5s
}
Вы можете использовать его где угодноstd::chrono::duration
, он имеет все те же функциональные возможности, и поскольку он определен в пространстве имен lib
, его можно использовать с любыми другими функциями в пространстве имен lib
без префикса lib
!