我有某种类型的std::vector<T>
是类的一部分,我需要在代码中的许多不同位置进行迭代,所以我认为我会聪明并创建一个函数IterateAttributes,并传递一个boost :: function对象,我可以在循环中传递一个元素,然后我可以传递任何函数来处理元素。
这似乎是一个好主意,直到你必须实现它,然后问题来自传入的函数返回什么,它需要其他参数。看起来我要么必须找到一种更通用的方法,比如使用模板,或者我必须创建带有不同args的函数对象的重载。
我认为第一个(更通用的)选项可能更好,但是我怎么做呢?
下面是一个不起作用的试验,但是如果我想要一些args,除了属性(结构)arg之外的所有arg都是必需的。我应该怎么做呢?
template <typename T> template <typename arg>
void ElementNode::IterateAttributes(boost::function<T (arg, Attribute)> func_)
{
std::vector<Attribute>::iterator it = v_attributes.begin();
for (; it != v_attributes.end(); it++)
{
func_(arg, *it);
}
}
答案 0 :(得分:1)
这就是你的意思:
template <typename T, typename arg>
void ElementNode::IterateAttributes(boost::function<T (arg, Attribute)> func_, arg a)
{
std::vector<Attribute>::iterator it = v_attributes.begin();
for (; it != v_attributes.end(); it++)
{
func_(a, *it);
}
}
只允许任何类型的一个参数 - 如果您愿意,还可以引入更多参数的版本。
关于返回值 - 如何处理它取决于它实际上是什么价值 - 通用(可能是不必要的)解决方案是返回std::list<T>
,但这会产生比我想象的更多的问题。如果返回类型不同(不仅在类型上,而且在含义上),那么我建议修改模板化函数,以便它获取整体结果的引用/指针并相应地更新它:
template <typename T> template <typename arg>
void ElementNode::IterateAttributes(boost::function<voidT (arg, Attribute, T&)> func_)
{
std::vector<Attribute>::iterator it = v_attributes.begin();
T result;
for (; it != v_attributes.end(); it++)
{
func_(arg, *it, result);
}
return result;
}
这是一个快速的解决方法,它可以工作,但它很难看,容易出错,也很难调试。
如果你想要变量参数金额,那么你必须创建以上函数的几个模板 - 我只是测试了它是否可能:
template <typename T>
T boo(T){
}
template <typename T, typename TT>
TT boo(T,TT){
}
void test()
{
int i;
i= boo<int>(0);
i=boo<int,double>(0,0.0);
}
您必须记住,传递给IterateAttributes的函数必须与给予Iterate函数的exatly参数匹配。这也意味着你不能使用它的原型默认值 - 可能你必须定义几个重载版本,如
void func_(Attribute,arg1, arg2,arg3){...}
void func_(Attribute A,arg1 a1,arg2 a2){func_(A,a1, a2,default3);}
void func_(Attribute A,arg1 a1){func_(A,a1, default2,default3);}
void func_(Attribute A){func_(A,default1, default2,default3);}
答案 1 :(得分:0)
a)你想迭代数组并对那里的每个元素做一些事情:在这种情况下,你想要所有接受数组元素并返回void的函数。简单。
b)您希望在每个元素上部分应用具有更多参数的函数:在函数周围编写一个自定义函子来存储其他预先赋值的参数,或者使用boost::bind
来有效地执行相同操作。
示例:
vector<string> myStrings; // assign some values
// define a function with an additional argument
void myFunc(string message, string value)
{
cout << message << value << endl;
}
// allow partial application, i.e. "currying"
struct local_function
{
static string message;
static void myFunc_Curried(string value)
{
myFunc(message, value);
}
};
local_function::message = "the array contains: ";
// apply the curried function on all elements in the array
for_each(myStrings.begin(), myStrings.end(), local_function::myFunc_Curried);
仿函数仅用于演示目的而静态运行。如果将message
绑定到结构的实例,则无论如何都需要类似boost::bind
的绑定实例指针this
以实际调用curried函数。但是,如果我想要应用的函数仅在本地使用,我更喜欢使用更易读的静态方法。
您要完成的工作非常有意义,并且还直接构建到函数式语言中(例如F#)。可以用C ++实现,但在上述情况b中需要一些变通方法。请注意,如果在我的示例中编写自己的仿函数,通常会将您想要的参数始终放在开头,并在部分应用时从开头到结尾“填写”参数。 / p>
答案 2 :(得分:0)
总结评论和更多想法:
使用bind
绑定其他参数,然后在生成的仿函数上使用for_each
。
要处理返回值,您需要考虑返回值的含义。如果您需要以某种方式使用这些值(例如,执行缩小,或使用它们来影响是否继续执行操作等),那么您可以使用另一个仿函数来包装原始文件以执行您想要的操作
答案 3 :(得分:0)
您可以使用BOOST_FOREACH
或C ++ 0x for each
执行相同或更多操作。这甚至可以用更少的代码来编写。