boost::static_visitor 中 operator() 的附加参数
Additional argument in operator() in boost::static_visitor
我必须创建 boost::variant
对象并使用 static_visitor
。
不幸的是我需要额外的参数...
哪种解决方案更好?
要将此对象作为 class 的字段,当我想使用访问者时,我必须创建实例:
class Visitor : public boost::static_visitor<>
{
public:
Visitor(int extra): extra{extra} {}
void operator()(const T1&) { /* ... */}
void operator()(const T2&) { /* ... */}
private:
int extra;
};
并在每次我想使用它时创建 Visitor 对象:
Visitor visitor(x);
boost::apply_visitor(visitor, t);
或使用 boost::bind 并创建一次访问者并使用 boost::bind
?
class Visitor : public boost::static_visitor<>
{
public:
void operator()(const T1&, int extra) { /* ... */ }
void operator()(const T2&, int extra) { /* ... */ }
};
用法:
auto visitor = std::bind(SctpManager::Visitor(), std::placeholders::_1, extra);
boost::apply_visitor(visitor, t);
什么是更好(更快、更优雅)的解决方案?
或者有什么更好的解决方案吗?
没有本质上更优雅的方式。您可以使用 lambda(如果您的 compiler/boost 版本足够现代)。
"low-tech" 选项是使用保存状态的结构(第 3 个示例):
#include <boost/variant.hpp>
#include <iostream>
struct T1{};
struct T2{};
struct Visitor : boost::static_visitor<>
{
void operator()(T1 const&, int extra) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; }
void operator()(T2 const&, int extra) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; }
};
int main() {
boost::variant<T1, T2> tests[] = { T1{}, T2{} };
{
Visitor vis;
for (auto v: tests)
apply_visitor([=](auto const& v) { vis(v, 42); }, v);
}
{
auto vis = [vis=Visitor{}](auto const& v) { vis(v, 1); };
for (auto v: tests)
apply_visitor(vis, v);
}
{
struct {
using result_type = void;
int extra;
void operator()(T1 const&) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; }
void operator()(T2 const&) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; }
} vis { 99 };
for (auto v: tests)
apply_visitor(vis, v);
}
}
版画
void Visitor::operator()(const T1&, int) const extra:42
void Visitor::operator()(const T2&, int) const extra:42
void Visitor::operator()(const T1&, int) const extra:1
void Visitor::operator()(const T2&, int) const extra:1
void main()::<unnamed struct>::operator()(const T1&) const extra:99
void main()::<unnamed struct>::operator()(const T2&) const extra:99
我必须创建 boost::variant
对象并使用 static_visitor
。
不幸的是我需要额外的参数...
哪种解决方案更好? 要将此对象作为 class 的字段,当我想使用访问者时,我必须创建实例:
class Visitor : public boost::static_visitor<>
{
public:
Visitor(int extra): extra{extra} {}
void operator()(const T1&) { /* ... */}
void operator()(const T2&) { /* ... */}
private:
int extra;
};
并在每次我想使用它时创建 Visitor 对象:
Visitor visitor(x);
boost::apply_visitor(visitor, t);
或使用 boost::bind 并创建一次访问者并使用 boost::bind
?
class Visitor : public boost::static_visitor<>
{
public:
void operator()(const T1&, int extra) { /* ... */ }
void operator()(const T2&, int extra) { /* ... */ }
};
用法:
auto visitor = std::bind(SctpManager::Visitor(), std::placeholders::_1, extra);
boost::apply_visitor(visitor, t);
什么是更好(更快、更优雅)的解决方案?
或者有什么更好的解决方案吗?
没有本质上更优雅的方式。您可以使用 lambda(如果您的 compiler/boost 版本足够现代)。
"low-tech" 选项是使用保存状态的结构(第 3 个示例):
#include <boost/variant.hpp>
#include <iostream>
struct T1{};
struct T2{};
struct Visitor : boost::static_visitor<>
{
void operator()(T1 const&, int extra) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; }
void operator()(T2 const&, int extra) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; }
};
int main() {
boost::variant<T1, T2> tests[] = { T1{}, T2{} };
{
Visitor vis;
for (auto v: tests)
apply_visitor([=](auto const& v) { vis(v, 42); }, v);
}
{
auto vis = [vis=Visitor{}](auto const& v) { vis(v, 1); };
for (auto v: tests)
apply_visitor(vis, v);
}
{
struct {
using result_type = void;
int extra;
void operator()(T1 const&) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; }
void operator()(T2 const&) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; }
} vis { 99 };
for (auto v: tests)
apply_visitor(vis, v);
}
}
版画
void Visitor::operator()(const T1&, int) const extra:42
void Visitor::operator()(const T2&, int) const extra:42
void Visitor::operator()(const T1&, int) const extra:1
void Visitor::operator()(const T2&, int) const extra:1
void main()::<unnamed struct>::operator()(const T1&) const extra:99
void main()::<unnamed struct>::operator()(const T2&) const extra:99