是否有一种将元数据与C++中的函数相关联的整洁方式

Tim*_*ell 2 c++

我有一个包含许多命令行选项的代码库.目前,如果在命令行上传入命令,则每个命令行选项都与表中的函数指针一起存在于表中.

例如

static CommandFunction s_Commands[] =
{
   { "command1", Func1 },
   { "command2", Func2 },
   { "command3", Func3 },
   etc...
};
Run Code Online (Sandbox Code Playgroud)

我的问题是,表格很大,而且功能在其他地方.我更喜欢命令的字符串住在每个函数旁边.

例如:

COMMAND_ARG("command1")
void Func1()
{
    dostuff
    ...
}

COMMAND_ARG("command2")
void Func2()
{
    dostuff
    ...
}

COMMAND_ARG("command3")
void Func3()
{
    dostuff
    ...
}
Run Code Online (Sandbox Code Playgroud)

这可能吗?

Max*_*kin 6

您可以使用由函数地址专门设计的模板来执行此操作:

#include <stdio.h>

// In a header file.
template<void(*Fn)()>
struct FnMeta
{
    static char const* const meta;
};
// no definition of meta


// some.cc
void some() {}
template<> char const* const FnMeta<some>::meta = "some";

// another.cc
void another() {}
template<> char const* const FnMeta<another>::meta = "another";

// main.cc    
int main() {
    printf("%s\n", FnMeta<some>::meta);
    printf("%s\n", FnMeta<another>::meta);
}
Run Code Online (Sandbox Code Playgroud)

上面的想法FnMeta<>::meta是没有定义的.但是,不同的翻译单元(.cc文件)可以提供专业化的定义FnMeta<>::meta.这种方式在FnMeta<X>::meta使用时链接器在另一个转换单元中找到它的适当定义.

  • 我想这个问题的很大一部分是相反的.命令行的输入很可能是字符串,系统必须找出要调用的函数以提供字符串描述的功能. (2认同)

Dav*_*eas 5

这个特定问题有不同的方法.您可以使用继承,通过继承创建基础Command然后实现某些execute功能(您也可以实现help,validate....).然后创建一个调度程序函数,将函数名称与命令的实际实现相关联(在各种查找表中,可能是a map).

虽然这不能解决您的地方问题,但这个问题可能是真实的.也就是说,命令的实现可能到处都是,但是有一个地方可以确定CLI中可用的命令.

如果locality对您来说非常重要(代价是在源代码中没有一个位置,其中列出了所有使用的命令),您可以提供全局可访问的注册机制,然后提供一个帮助器类型,施工将把功能登记到机制中.然后,您可以使用每个函数定义创建一个此类对象.

CommandRegistry& getCommandRegistry();    // Access the registry
struct CommandRegister {
   CommandRegister(const char* name, Function f) {
      getCommandRegistry().registerCmd(name,f);
   }
   // Optionally add deregistration
};
// ...
void Func2() {...}
static CommandRegister Func2Registration("function2",&Func2);
Run Code Online (Sandbox Code Playgroud)

我个人更喜欢走另一条路...在代码中有一个单独的位置列出所有命令,因为它允许在一个位置找到执行它的代码的命令(文本).也就是说,当您有一些命令而其他人需要维护其中一个命令时,它会更容易从命令行转到执行它的实际代码.