Từ các tài liệu boost::fusion
:
Các I/O khai thác đang bị quá tải trong thúc đẩy namespace :: fusion
Điều đó có nghĩa rằng nếu bạn muốn có một hội nhập tiềm ẩn của những operator<<
, bạn sẽ cần phải tiêm không gian tên boost::fusion
vào không gian tên hiện tại của mình (::
tại đây) hoặc sử dụng chúng một cách rõ ràng.
Tổng hợp tất cả lên, nói thêm:
using namespace boost::fusion;
nên làm việc trong trường hợp của bạn. Hoặc cho việc sử dụng rõ ràng, bạn sẽ phải viết:
boost::fusion::operator<<(std::cout, e) << std::endl;
--- EDIT ---
Sau khi đọc mã boost::fusion
's một chút, nó có vẻ rằng bạn đang bối rối vì Tra cứu của Koenig của boost::fusion::operators::operator<<
được chọn trong trường hợp đối số của bạn là boost::fusion::sequence
thực.
Đây là lý do tại sao bạn không cần phải tiêm không gian tên boost::fusion
, cũng không gọi boost::fusion::operator<<
cho các loại được xác định trong không gian tên boost::fusion
.
Một số giải thích:
Tôi sẽ không giải thích toàn bộ khái niệm về tra cứu Koenig (còn được gọi là Argument Dependent Lookup - ADL) ở đây vì đó không phải là vấn đề, nhưng về cơ bản, nó khẳng định rằng trong trường hợp bạn đang sử dụng một biến có kiểu nằm bên trong một không gian tên, sau đó tìm kiếm hàm mở rộng đến vùng tên của tham số đó.
Trong trường hợp cụ thể này, bao gồm boost/fusion/sequence/io/out.hpp
sẽ xác định boost::fusion::operator::operator<<
sau đó sẽ được đưa vào không gian tên boost::fusion
.
$ cat /usr/local/include/boost/fusion/sequence/io/out.hpp
[...]
namespace boost { namespace fusion
{
[...]
namespace operators
{
template <typename Sequence>
inline typename
boost::enable_if<
fusion::traits::is_sequence<Sequence>
, std::ostream&
>::type // this is just a SFINAE trick to ensure
// the function will only be selected for
// actual boost::fusion::sequence
operator<<(std::ostream& os, Sequence const& seq)
{
return fusion::out(os, seq); // this will print out the sequence
}
}
using operators::operator<<; // here the operator<< is injected
// in boost::fusion
}}
Điều này có nghĩa rằng các cuộc gọi sử dụngoperator<<
với các thông số có loại là trong không gian tênboost::fusion
sẽ tìm thấy sự quá tải thích hợp.
Cuộc gọi sử dụng các đối số có loại không nằm trong không gian tên này sẽ không giải quyết được tình trạng quá tải thích hợp của operator<<
(đây là trường hợp trong ví dụ của bạn).
Bạn có thể kiểm tra điều đó bằng cách xác định loại của bạn trong không gian tên boost::fusion
.
namespace boost { namespace fusion {
struct employee
{
std::string name;
int age;
};
}}
BOOST_FUSION_ADAPT_STRUCT(
boost::fusion::employee,
(std::string, name)
(int, age))
[...]
boost::fusion::employee e;
std::cout << e << std::endl; // ADL will work here
Lưu ý phụ: Nếu bạn muốn gỡ lỗi các vấn đề tra cứu tên, bạn nên sử dụng gdb
. Bằng cách đó bạn sẽ luôn biết được tình trạng quá tải nào đã được chọn. Trong trường hợp này:
$ cat fusion.cpp
#include <iostream>
#include <cstdlib>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/io.hpp>
int main(int, char**)
{
boost::fusion::vector<int, char> foo(42, '?');
std::cout << foo << std::endl;
return EXIT_SUCCESS;
}
$ gdb -q ./fusion
Reading symbols for shared libraries ... done
(gdb) b 10
Breakpoint 1 at 0x1000012f7: file fusion.cpp, line 10.
(gdb) r
Starting program: /Users/avallee/Projects/tmp/fusion
Reading symbols for shared libraries ++............................. done
Breakpoint 1, main (unnamed_arg=0x7fff5fbffb60, unnamed_arg=0x7fff5fbffb60) at fusion.cpp:10
10 std::cout << foo << std::endl;
(gdb) s
boost::fusion::operators::operator<< <boost::fusion::vector<int, char, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > ([email protected], [email protected]) at out.hpp:38
38 return fusion::out(os, seq);