sti*_*tix 1 c++ boost visitor-pattern boost-variant
我正在尝试使用boost :: static_visitor在boost :: variant类型上实现影响某些变量状态的操作.我的方法是在命令访问者类中包含所有状态变量,但似乎这是不可能的.
这是我的代码示例:
#include <string>
#include <sstream>
#include <vector>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
struct TypeA
{
int varA;
int varB;
};
struct TypeB
{
std::string varA;
std::string varB;
};
typedef boost::variant<TypeA, TypeB> MyVariantType;
class MyCommandVisitor : public boost::static_visitor<>
{
public:
//These are just examples, the actions only need to be able to touch
// internal variables.
void operator()(TypeA & t) const
{
m_runningSum += t.varA;
m_outStream << "TYPEA ACTION: " << t.varB << std::endl;
}
void operator(TypeB & t) const
{
m_charCount += t.varA.size();
m_outStream << t.varB << " ACTION " << t.varA << std::endl;
}
std::string emitWork(std::vector<MyVariantType> listOfVariants)
{
m_outStream.clear();
m_runningSum = 0;
m_charCount = 0;
BOOST_FOREACH(MyVariantType & v, listOfVariants)
{
boost::apply_visitor(*this, v);
}
return m_outStream.str();
}
protected:
int m_runningSum;
int m_charCount;
std::stringstream outStream;
}; //End class MyCommandVisitor
int main(int argc, char **argv)
{
TypeA ta;
ta.varA = 1;
ta.varB = 2;
TypeB tb;
tb.varA = "String1";
tb.varB = "String2";
std::vector<MyVariantType> listOfWork;
listOfWork.push_back(ta);
listOfWork.push_back(tb);
MyCommandVisitor myCV;
std::string result = myCV.emitWork(listOfWork);
std::cout << "Result:\n" << result << std::endl << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望这个片段能够理解我想要实现的目标.但是,它不会编译,给出[释义]错误:
error: no operator "<<" matches these operands
operand types are: const std::stringstream << const char [N]
m_outStream << "TYPE A ACTION: " << t.varB << std::endl;
^
Run Code Online (Sandbox Code Playgroud)
我假设这个错误是由于const修饰符必须放在operator()函数原型的末尾,这使得编译器认为成员变量不能被函数修改.
我的问题是:
使用必须在访问之间保持状态的变量来完成访问者模式(使用boost :: variant)的正确方法是什么?
有几个错别字,但我做了一些mods,它现在有效.基本上你的static_visitor类在每次访问时都会发生变化,因此operator()方法不能是const.
#include <string>
#include <sstream>
#include <vector>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
#include <iostream>
struct TypeA
{
int varA;
int varB;
};
struct TypeB
{
std::string varA;
std::string varB;
};
typedef boost::variant<TypeA, TypeB> MyVariantType;
class MyCommandVisitor : public boost::static_visitor<>
{
public:
//These are just examples, the actions only need to be able to touch
// internal variables.
void operator()(TypeA & t)
{
m_runningSum += t.varA;
m_outStream << "TYPEA ACTION: " << t.varB << std::endl;
}
void operator()(TypeB & t)
{
m_charCount += t.varA.size();
m_outStream << t.varB << " ACTION " << t.varA << std::endl;
}
std::string emitWork(std::vector<MyVariantType> listOfVariants)
{
m_outStream.clear();
m_runningSum = 0;
m_charCount = 0;
BOOST_FOREACH(MyVariantType & v, listOfVariants)
{
boost::apply_visitor(*this, v);
}
return m_outStream.str();
}
protected:
int m_runningSum;
int m_charCount;
std::stringstream m_outStream;
}; //End class MyCommandVisitor
int main(int argc, char **argv)
{
TypeA ta;
ta.varA = 1;
ta.varB = 2;
TypeB tb;
tb.varA = "String1";
tb.varB = "String2";
std::vector<MyVariantType> listOfWork;
listOfWork.push_back(ta);
listOfWork.push_back(tb);
MyCommandVisitor myCV;
std::string result = myCV.emitWork(listOfWork);
std::cout << "Result:\n" << result << std::endl << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在http://www.compileonline.com/compile_cpp11_online.php上运行给出:
Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
Result:
TYPEA ACTION: 2
String2 ACTION String1
Run Code Online (Sandbox Code Playgroud)