【问题标题】:Create functions in preproccesor in C++在 C++ 的预处理器中创建函数
【发布时间】:2014-02-03 05:27:07
【问题描述】:

我在 Arduino IDE 中使用了一个计时器库,该库具有一个函数,该函数将“void(*func)(void)”作为参数并在一定时间后运行它。我需要在我的代码中传递一个函数库,问题是我需要做同样事情的“n”个函数(只是函数内部涉及的变量采用不同的值,我从结构数组中获取),这就是为什么我不能只使用一个函数,我需要能够编译具有相同语法但涉及不同变量的不同函数。

我不知道如何解决这个问题,我想做的是能够像在 for 循环中一样创建函数,

for(int i=0;i<MAX_FUNC;i++)
{    
void func[i](){
x= structuredata.x[i];
}
}

我知道这种语法是完全错误的,但我想知道如何才能实现这样的目标。我尝试改用类,但库不允许我使用在类中创建的 void 函数作为参数,它表示“未解析的重载函数类型”

【问题讨论】:

  • 你是指模板之类的东西吗?
  • 是的,我希望能够创建函数,只修改函数名称和我想在函数内部访问的数组
  • 我想您是在问如何复制粘贴功能,例如 func1() { x = data.x[1]; } 然后 func2func3 等等。必须有更好的方法来解决您的问题问题!例如,只需让您的函数采用 int i 并将函数设为 func(int i) { x = data.x[i]; } 或类似的东西?
  • 我见过的大多数采用类似回调的库,也采用额外的 void* 以便您可以将任意数据传递给您的函数,这样您就不会陷入这种情况。你确定你的定时器库不提供吗?
  • 哦,它甚至是一个 C++ 库而不是 C。非常糟糕。我会毫不犹豫地分叉它。可能使用模板仿函数 ir std::function 代替。

标签: c++


【解决方案1】:

如果您喜欢模板覆盖并且可以像这样重构您的函数,那么打包一堆要连续触发的回调的解决方案比您想象的更接近。如果函数的一致性在字面上是相同的,您可以使它更通用。 IE。你可以这样做:

#include <iostream>

int ar[5] = { 1,2,3,4,5 };

// your function here
template <int i>
void callback()
{
    // your code here. i is provided
    int x = ar[i];
    std::cout << "Got Value: " <<  x << '\n';
};

////////////////////////////////////////////////////////////

// unraveller
template<int N>
void callback_set()
{
    callback_set<N-1>();
    callback<N-1>();
}

// base callback set
template<>
void callback_set<0>() {}

////////////////////////////////////////////////////////////

int main()
{
    callback_set<3>();
    return 0;
}

输出

Got Value: 1
Got Value: 2
Got Value: 3

您“注册”callback_set&lt;N&gt; 作为您的回调,它会为您链接对您的函数的调用。如果需要对不同实现的个性化访问,您仍然可以使用完整的专业化:

#include <iostream>

// prototypes
template <int i>
void callback() {};

// your functions here
template<>
void callback<0>()
{
    std::cout << "Callback #0" << '\n';
}

template<>
void callback<1>()
{
    std::cout << "Callback #1" << '\n';
}

template<>
void callback<2>()
{
    std::cout << "Callback #2" << '\n';
}
////////////////////////////////////////////////////////////


// unraveller
template<int N>
void callback_set()
{
    callback_set<N-1>();
    callback<N-1>();
}

// base callback set
template<>
void callback_set<0>() {}
////////////////////////////////////////////////////////////

int main()
{
    callback_set<3>();
    return 0;
}

输出

Callback #0
Callback #1
Callback #2

本质上,您使用callback_set&lt;N&gt; 对注册的回调进行样式化,其中N 是您为其提供覆盖的回调数量。只是一个想法,但如果我理解正确的话,这似乎是一个相当优雅的解决您的问题的方法。

【讨论】:

    【解决方案2】:

    为此你需要一些元编程......

    const int MAX_FUNC = 1000;
    
    typedef void (*Tcallback)();
    struct Tdata
    {
        int whatever;
    };
    
    Tdata callbackData[MAX_FUNC];
    Tcallback callbacks[MAX_FUNC];
    
    template <int index>
    void callbackToIndex()
    {
    //  callback knows it's index and thus can access some global structure for it's data
        printf("%u", index);
        callbackData[index];
    }
    
    template <int index>
    void callbackCreate()
    {
        callbacks[index] = &callbackToIndex<index>;
        callbackCreate<index - 1>();
    }
    template <>
    void callbackCreate<-1>()
    {
    }
    
    void create()
    {
        callbackCreate<MAX_FUNC - 1>();
    }
    

    【讨论】:

    • 作为旁注:您最好创建自己的调度程序(即在 Arduiono 中仅注册一个计时器,并在回调中调用第一个预定函数,然后注册下一个预定函数....)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-06
    • 2023-03-13
    • 1970-01-01
    • 2014-04-13
    • 2017-09-27
    • 2020-03-14
    • 1970-01-01
    相关资源
    最近更新 更多