Understanding ADL: Argument dependent lookup with logging
(JP 26/06/2015 originally presented during a live coding of the supporting code using BOOST_LOG_TRIVIAL)
ADL is there to enable working with namespaces seamlessly. What it means is that the set of overload for a function will include the overloads
- Defined in the namespace the argument types are defined in.
- Defined in the namespace the template parameter of the argument types are defined in.
- Many more obscure rules.
- For Example:
- look for overload in std for std::vector, std::set, std::pair.
- look for overload in geo for geo::Point, geo::Circle, std::vector< geo::Point > …
- look for overload in the global namespace for object defined in the global namespace.
- For built in types, no extra overload are added.
//
// Demo using ADL to write to a log file
//
#include <iostream>
#include <string>
#include <vector>
namespace geo {
struct Position
{
Position( int position ) : m_position( position ) {}
int m_position;
};
std::ostream& operator<<( std::ostream& os, const Position& pos )
{
return os << "Pos(" << pos.m_position << ")";
}
std::ostream& operator<<( std::ostream& os, const std::vector< Position >& positions )
{
for( auto& pos : positions )
{
os << pos << ", ";
}
return os;
}
} // namespace geo
class Dog
{
};
std::ostream& operator<<( std::ostream& os, const Dog& dog )
{
return os << "Wooof woof";
}
std::ostream& operator<<( std::ostream& os, const std::vector< Dog >& dogs )
{
for( auto& dog : dogs )
{
os << dog << ", ";
}
return os;
}
namespace forlog {
struct Wrapper
{
Wrapper( std::vector< int > vals ) : m_vals( vals ) {}
std::vector< int > m_vals;
};
std::ostream& operator<<( std::ostream& os, const Wrapper& integers )
{
for( auto& integer : integers.m_vals )
{
os << integer << ", ";
}
return os;
}
} // namespace forlog
namespace log {
void RunTest()
{
geo::Position position( 20 );
std::vector< geo::Position > positions = { 10, 30, 50 };
std::vector< int > integers = { 10, 30, 50 };
Dog dog;
std::vector< Dog > dogs( 20 );
std::cout << "A trace severity message" << '\n';
std::cout << dog << " " << position << '\n';
std::cout << positions << '\n';
std::cout << dogs << '\n';
std::cout << forlog::Wrapper( integers ) << '\n';
}
} // namespace log
int main(int argc, char* argv[])
{
log::RunTest();
return 0;
}
Presented at IndigoVision during a training session on 26/06/2015.
This work by Jean-Philippe DUFRAIGNE is licensed under a Creative Commons Attribution 4.0 International License.