如何循环异构 类 的实例以调用具有相同名称和参数的方法?
How can I cycle on instances of heterogenous classes to call methods with identical name and parameters?
如果我有:
class A {
void foo();
};
class B {
void foo();
};
有没有办法收集A
和B
类型的实例,循环调用foo()
方法?例如使用一些宏或指针和一些特殊的数据类型?或者收集函数指针?
以下伪代码可能让您明白我的意思。
int main () {
A a;
B b;
hypothetical_container_t hypothetical_container;
hypothetical_container.push_back(a);
hypothetical_container.push_back(b);
[...]//Do stuff with a, do other stuff with b
for (hypothetical_container_t::iterator ii = hypothetical_container.begin(); ii != hypothetical_container.end(); ++ii) {
ii->foo();
}
}
用例有一堆 boost::shared_ptr
个不同类型 T 的变量,并对所有变量调用 .reset()
。 (我知道在这个例子中调用 reset 是不必要的)。
您应该可以使用虚拟 class:
virtual class C {
public:
virtual void foo() = 0;
}
class A : public C {
virtual void foo();
};
class B : public C {
virtual void foo();
};
然后在主要你可以有:
A a;
B b;
std::vector<C*> vec;
vec.push_back(&a);
vec.push_back(&b);
然后可以迭代调用foo方法,vector的所有成员都保证实现
WRT boost::shared_ptr,我不太熟悉,但我想你可以这样做:
boost::shared_ptr<C> a(new A);
boost::shared_ptr<C> b(new B);
std::vector<boost::shared_ptr<C>> vec;
How can I cycle on instances of heterogenous classes to call methods
with identical name and parameters?
这需要模板!
#include <memory>
#include <iostream>
void chain_call_reset()
{
}
template<typename Arg, typename ... Rest>
void chain_call_reset(Arg&& arg, Rest&&... rest)
{
arg.reset();
chain_call_reset(rest...);
}
int main()
{
std::shared_ptr<int> ptr = std::make_shared<int>(42);
std::shared_ptr<char> ptr2 = std::make_shared<char>('c');
std::shared_ptr<float> ptr3 = std::make_shared<float>(4.2);
chain_call_reset(ptr, ptr2, ptr3);
std::cout << std::boolalpha << !!ptr << std::endl;
std::cout << std::boolalpha << !!ptr2 << std::endl;
std::cout << std::boolalpha << !!ptr3 << std::endl;
}
如果您的类型之间没有共同的层次结构,模板是可行的方法:)
如果您可以选择更改 类 A 和 B,我建议您使用 。
如果你没有那个选项,我有以下建议。
#include <memory>
#include <iostream>
#include <vector>
struct A {
void foo(){}
};
struct B {
void foo(){}
};
struct Wrapper
{
virtual void foo() = 0;
};
template <typename T> struct WrapperImpl : Wrapper
{
WrapperImpl(T& obj) : obj_(obj) {}
void foo() {obj_.foo();}
T& obj_;
};
template <typename T>
std::unique_ptr<Wrapper> makeWrapper(T& t)
{
return std::unique_ptr<Wrapper>(new WrapperImpl<T>(t));
}
int main()
{
std::vector<std::unique_ptr<Wrapper>> v;
A a;
B b;
v.push_back(makeWrapper(a));
v.push_back(makeWrapper(b));
for ( auto& item : v )
{
item->foo();
}
}
您的任务需要类型省略。 Boost::any 就是一个很好的例子。
调用普通函数的简单方法:
#include <iostream>
#include <memory>
#include <vector>
class Any
{
// Content
// =======
private:
class ContentInterface
{
public:
virtual ~ContentInterface() {}
virtual void call() const {}
};
template <typename T>
class Content : public ContentInterface
{
private:
T& m_object;
public:
Content(T& object)
: m_object(object)
{}
virtual void call() const { m_object.foo(); }
};
// use boost here:
typedef std::shared_ptr<ContentInterface> content_ptr;
// Constructionn
// =============
public:
Any()
{}
template<typename T>
Any(T& object)
: m_content(new Content<T>(object))
{}
void call() const { m_content->call(); }
private:
content_ptr m_content;
};
struct A {
void foo() { std::cout << "A\n"; }
};
struct B {
void foo() { std::cout << "B\n"; }
};
int main(void)
{
typedef std::vector<Any> container;
A a;
B b;
container v;
v.push_back(a);
v.push_back(b);
for(container::const_iterator pos = v.begin(); pos != v.end(); ++pos)
pos->call();
}
另一种选择是 std::function 和 std::bind(同样,在 C++98 中使用增强功能):
#include <functional>
#include <iostream>
#include <vector>
int main()
{
typedef std::function<void ()> function;
typedef std::vector<function> container;
A a;
B b;
container v;
v.push_back(std::bind(&A::foo, a));
v.push_back(std::bind(&B::foo, b));
for(container::const_iterator pos = v.begin(); pos != v.end(); ++pos)
(*pos)();
}
如果您无法访问可变参数模板,您可以使用 boost::fusion
:
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/for_each.hpp>
struct reset
{
template<typename T>
void operator()(T& t) const
{
t.reset();
}
};
int main()
{
boost::shared_ptr<int> ptr = boost::make_shared<int>(42);
boost::shared_ptr<char> ptr2 = boost::make_shared<char>('c');
boost::shared_ptr<float> ptr3 = boost::make_shared<float>(4.2);
boost::fusion::vector<boost::shared_ptr<int>&, boost::shared_ptr<char>&, boost::shared_ptr<float>& > vec
= boost::fusion::make_vector(boost::ref(ptr), boost::ref(ptr2), boost::ref(ptr3));
boost::fusion::for_each(vec, reset());
std::cout << std::boolalpha << !!ptr << std::endl;
std::cout << std::boolalpha << !!ptr2 << std::endl;
std::cout << std::boolalpha << !!ptr3 << std::endl;
}
如果我有:
class A {
void foo();
};
class B {
void foo();
};
有没有办法收集A
和B
类型的实例,循环调用foo()
方法?例如使用一些宏或指针和一些特殊的数据类型?或者收集函数指针?
以下伪代码可能让您明白我的意思。
int main () {
A a;
B b;
hypothetical_container_t hypothetical_container;
hypothetical_container.push_back(a);
hypothetical_container.push_back(b);
[...]//Do stuff with a, do other stuff with b
for (hypothetical_container_t::iterator ii = hypothetical_container.begin(); ii != hypothetical_container.end(); ++ii) {
ii->foo();
}
}
用例有一堆 boost::shared_ptr
个不同类型 T 的变量,并对所有变量调用 .reset()
。 (我知道在这个例子中调用 reset 是不必要的)。
您应该可以使用虚拟 class:
virtual class C {
public:
virtual void foo() = 0;
}
class A : public C {
virtual void foo();
};
class B : public C {
virtual void foo();
};
然后在主要你可以有:
A a;
B b;
std::vector<C*> vec;
vec.push_back(&a);
vec.push_back(&b);
然后可以迭代调用foo方法,vector的所有成员都保证实现
WRT boost::shared_ptr,我不太熟悉,但我想你可以这样做:
boost::shared_ptr<C> a(new A);
boost::shared_ptr<C> b(new B);
std::vector<boost::shared_ptr<C>> vec;
How can I cycle on instances of heterogenous classes to call methods with identical name and parameters?
这需要模板!
#include <memory>
#include <iostream>
void chain_call_reset()
{
}
template<typename Arg, typename ... Rest>
void chain_call_reset(Arg&& arg, Rest&&... rest)
{
arg.reset();
chain_call_reset(rest...);
}
int main()
{
std::shared_ptr<int> ptr = std::make_shared<int>(42);
std::shared_ptr<char> ptr2 = std::make_shared<char>('c');
std::shared_ptr<float> ptr3 = std::make_shared<float>(4.2);
chain_call_reset(ptr, ptr2, ptr3);
std::cout << std::boolalpha << !!ptr << std::endl;
std::cout << std::boolalpha << !!ptr2 << std::endl;
std::cout << std::boolalpha << !!ptr3 << std::endl;
}
如果您的类型之间没有共同的层次结构,模板是可行的方法:)
如果您可以选择更改 类 A 和 B,我建议您使用
如果你没有那个选项,我有以下建议。
#include <memory>
#include <iostream>
#include <vector>
struct A {
void foo(){}
};
struct B {
void foo(){}
};
struct Wrapper
{
virtual void foo() = 0;
};
template <typename T> struct WrapperImpl : Wrapper
{
WrapperImpl(T& obj) : obj_(obj) {}
void foo() {obj_.foo();}
T& obj_;
};
template <typename T>
std::unique_ptr<Wrapper> makeWrapper(T& t)
{
return std::unique_ptr<Wrapper>(new WrapperImpl<T>(t));
}
int main()
{
std::vector<std::unique_ptr<Wrapper>> v;
A a;
B b;
v.push_back(makeWrapper(a));
v.push_back(makeWrapper(b));
for ( auto& item : v )
{
item->foo();
}
}
您的任务需要类型省略。 Boost::any 就是一个很好的例子。 调用普通函数的简单方法:
#include <iostream>
#include <memory>
#include <vector>
class Any
{
// Content
// =======
private:
class ContentInterface
{
public:
virtual ~ContentInterface() {}
virtual void call() const {}
};
template <typename T>
class Content : public ContentInterface
{
private:
T& m_object;
public:
Content(T& object)
: m_object(object)
{}
virtual void call() const { m_object.foo(); }
};
// use boost here:
typedef std::shared_ptr<ContentInterface> content_ptr;
// Constructionn
// =============
public:
Any()
{}
template<typename T>
Any(T& object)
: m_content(new Content<T>(object))
{}
void call() const { m_content->call(); }
private:
content_ptr m_content;
};
struct A {
void foo() { std::cout << "A\n"; }
};
struct B {
void foo() { std::cout << "B\n"; }
};
int main(void)
{
typedef std::vector<Any> container;
A a;
B b;
container v;
v.push_back(a);
v.push_back(b);
for(container::const_iterator pos = v.begin(); pos != v.end(); ++pos)
pos->call();
}
另一种选择是 std::function 和 std::bind(同样,在 C++98 中使用增强功能):
#include <functional>
#include <iostream>
#include <vector>
int main()
{
typedef std::function<void ()> function;
typedef std::vector<function> container;
A a;
B b;
container v;
v.push_back(std::bind(&A::foo, a));
v.push_back(std::bind(&B::foo, b));
for(container::const_iterator pos = v.begin(); pos != v.end(); ++pos)
(*pos)();
}
如果您无法访问可变参数模板,您可以使用 boost::fusion
:
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/for_each.hpp>
struct reset
{
template<typename T>
void operator()(T& t) const
{
t.reset();
}
};
int main()
{
boost::shared_ptr<int> ptr = boost::make_shared<int>(42);
boost::shared_ptr<char> ptr2 = boost::make_shared<char>('c');
boost::shared_ptr<float> ptr3 = boost::make_shared<float>(4.2);
boost::fusion::vector<boost::shared_ptr<int>&, boost::shared_ptr<char>&, boost::shared_ptr<float>& > vec
= boost::fusion::make_vector(boost::ref(ptr), boost::ref(ptr2), boost::ref(ptr3));
boost::fusion::for_each(vec, reset());
std::cout << std::boolalpha << !!ptr << std::endl;
std::cout << std::boolalpha << !!ptr2 << std::endl;
std::cout << std::boolalpha << !!ptr3 << std::endl;
}