用于控制算法的函子的编译时容器?

发布于 2024-10-01 07:19:32 字数 670 浏览 5 评论 0原文

假设我想要如下简单的东西:

我有一个核心算法,它随机选择一种专用算法(在编译时专用)并处理该算法。这些专门的算法是通过函子实现的。

现在的问题:如何实现一个在编译时构建的容器,其中核心算法可以首先检查该容器的大小(“我有 4 个算法 -> 需要随机选择算法 0-3”),然后可以执行该容器中的函子(“随机选择 2 -> 处理容器中的第三个函子”)。

如何尽可能简单地实现它?我想这是可能的。

奇怪地重复出现的模板习惯有任何联系吗? (wiki 链接
使用Boost::Fusion有简单的方法吗? (官方文档)

编辑:所有算法都将在核心算法中使用。使用模式(随机数)是运行时决定(所以我不需要编译时随机数)。该算法只需知道函子的容器以及该容器的大小即可安全访问。

Suppose i want something simple like the following:

I have an core-algorithm, which randomly selects one of the specialized algorithms (specialized at compile-time) and process this algorithm. These specialized algorithms are implemented trough functors.

The question is now: how to implement a container, which is build at compile-time, where the core-algorithm can first check the size of this container ("i got 4 algorithms -> need to randomly select algorithm 0-3") and can then execute the functor in this container ("randomly chosen 2 -> process the third functor in container").

How would one implement it as simple as possible? I suppose it is possible.

Is there any connection to the curiously recurring template idiom? (wiki link)
Is there a simple way with the use of Boost::Fusion? (official doc)

Edit: All the algorithms will be used in the core-algorithm. The use pattern (random-numbers) is a runtime-decision (so i don't need compile-time-rands). The algorithm just has to know the container of functors and the size of this container for safe access.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烈酒灼喉 2024-10-08 07:19:32

如果您希望核心算法执行专用算法,则核心算法和专用算法之间应该存在某种契约。

如果您将此合约定义为接口,则您的容器只是一个包含指向这些接口的指针的容器,例如:

class IAlgorithm
   {
   public:
      virtual double operator()(double d) = 0;
   };

typedef std::vector<IAlgorithm *> Algorithms;

调用随机算法只是简单地获取向量的大小,获取零和列表大小之间的随机值( 0..size-1),获取该位置的条目并调用接口。

或者,您也可以使用新的 C++0x std::function 构造,如下所示:

#include <functional>
typedef std::function<double(double)> Algorithm;
typedef std::vector<Algorithm> Algorithms;

采用类似的算法,您应该能够调用如下算法:

Algorithms myAlgorithms;
...
double myresult = myAlgorithms[2](mydouble);

这种方法的优点是您还可以使用 lambda。

编辑:这是一个使用 lambda 的示例。它可以在 Visual Studio 2010 中按预期进行编译和工作(我自己刚刚测试过):

#include <iostream>
#include <vector>
#include <functional> 
typedef std::function<double(double)> Algorithm; 
typedef std::vector<Algorithm> Algorithms; 

int main()
{
Algorithms algorithms;
algorithms.push_back([](double d)->double{return d+d;});
algorithms.push_back([](double d)->double{return d*d;});

std::cout << algorithms[0](5) << std::endl;
std::cout << algorithms[1](5) << std::endl;
}

If you want your core-algorithm to execute a specialized algorithm, there should be some kind of contract between the core-algorithm and the specialized algorithm.

If you define this contract as an interface, your container is simply a container containing pointers to these interfaces, e.g.:

class IAlgorithm
   {
   public:
      virtual double operator()(double d) = 0;
   };

typedef std::vector<IAlgorithm *> Algorithms;

Calling a random algorithm is then simply taking the size of the vector, taking a random value between zero and the size of the list (0..size-1), taking the entry at that position and calling the interface.

Alternatively, you can also use the new C++0x std::function construction, like this:

#include <functional>
typedef std::function<double(double)> Algorithm;
typedef std::vector<Algorithm> Algorithms;

Taking an algorithm is similar, you should be able to call an algorithm like this:

Algorithms myAlgorithms;
...
double myresult = myAlgorithms[2](mydouble);

This approach has the advantage that you can also use lambda's.

EDIT: This is an example that uses lambda's. It compiles and works as expected with Visual Studio 2010 (just tested this myself):

#include <iostream>
#include <vector>
#include <functional> 
typedef std::function<double(double)> Algorithm; 
typedef std::vector<Algorithm> Algorithms; 

int main()
{
Algorithms algorithms;
algorithms.push_back([](double d)->double{return d+d;});
algorithms.push_back([](double d)->double{return d*d;});

std::cout << algorithms[0](5) << std::endl;
std::cout << algorithms[1](5) << std::endl;
}
澜川若宁 2024-10-08 07:19:32

我不是专家,但我认为确实 boost::fusion 和/或 boost::mpl 是您正在寻找的工具。

您的类将采用 mpl 容器作为参数,作为算法函子类型的列表,然后在编译时使用它。

I'm not a specialist but I think that indeed boost::fusion and/or boost::mpl are the tools you're looking for.

Your class would take an mpl container as parameter, being the list of algorithms functor types, and then would work with it at compile time.

自演自醉 2024-10-08 07:19:32

我认为一个有趣的子问题是如何在编译时生成随机数。

也许是这样的:)

//compiletime_rand.h

#ifndef COMPILETIME_RAND_GENERATOR_H
#define COMPILETIME_RAND_GENERATOR_H

template <unsigned N, unsigned Seed, unsigned Modulo>
struct rand_c_impl
{
    static const unsigned value_impl = (1664525 * rand_c_impl<N - 1, Seed, Modulo>::value + 1013904223) % (1ull << 32);
    static const unsigned value = value_impl % Modulo;
};

template <unsigned Seed, unsigned Modulo>
struct rand_c_impl<0, Seed, Modulo>
{
    static const unsigned value_impl = Seed;
    static const unsigned value = value_impl;
};

#endif

//next_c_rand.h

#include BOOST_PP_UPDATE_COUNTER()

rand_c_impl<BOOST_PP_COUNTER, 0, MAX_C_RAND>::value

//main.cpp

#include <boost/preprocessor/slot/counter.hpp>
#include "compiletime_rand.h"

#include <iostream>

#define MAX_C_RAND 16

template <unsigned N>
void output_compiletime_value()
{
    std::cout << N << '\n';
}

int main()
{
    output_compiletime_value< 
#include "next_c_rand.h"
    >();
    output_compiletime_value< 
#include "next_c_rand.h"
    >();  
}

输出:15 2

I think an interesting subproblem is how to generate random numbers at compile-time.

Perhaps something like this :)

//compiletime_rand.h

#ifndef COMPILETIME_RAND_GENERATOR_H
#define COMPILETIME_RAND_GENERATOR_H

template <unsigned N, unsigned Seed, unsigned Modulo>
struct rand_c_impl
{
    static const unsigned value_impl = (1664525 * rand_c_impl<N - 1, Seed, Modulo>::value + 1013904223) % (1ull << 32);
    static const unsigned value = value_impl % Modulo;
};

template <unsigned Seed, unsigned Modulo>
struct rand_c_impl<0, Seed, Modulo>
{
    static const unsigned value_impl = Seed;
    static const unsigned value = value_impl;
};

#endif

//next_c_rand.h

#include BOOST_PP_UPDATE_COUNTER()

rand_c_impl<BOOST_PP_COUNTER, 0, MAX_C_RAND>::value

//main.cpp

#include <boost/preprocessor/slot/counter.hpp>
#include "compiletime_rand.h"

#include <iostream>

#define MAX_C_RAND 16

template <unsigned N>
void output_compiletime_value()
{
    std::cout << N << '\n';
}

int main()
{
    output_compiletime_value< 
#include "next_c_rand.h"
    >();
    output_compiletime_value< 
#include "next_c_rand.h"
    >();  
}

Output: 15 2

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文