使宏为不存在的函数产生编译时错误

Make macro produce compile time error for non-existing function

我在命名空间中有几个函数。参数不同,对于每次调用,它们都会将包含字符串成员的对象存储到向量中。 命名空间中没有重载函数。

我想创建一个宏来生成 lambda 表达式,用于匹配通过调用某个函数创建的对象。除此之外,如果命名空间中不存在具有作为参数提供的名称的函数,宏还应该导致编译时错误。编译成功会影响结果吗? (如果可能的话,有和没有这个检查的编译结果将是相同的,而不依赖于可能会或可能不会根据优化级别优化的代码。)这可能吗?如果可能:我该如何实施?

我正在努力实现的示例;我要问的宏是 CALL_INFO_PREDICATE; static_assert_function_exists 部分是任何可实现预期结果的代码的占位符:

struct CallInfo
{
    const std::string m_function;
    CallInfo(const std::string& function)
        : m_function(function)
    {
    }
}

std::vector<CallInfo*> g_calledFunctions;

namespace mymath
{

    // all functions with same return type, but differnent parameter lists

    double sin(double radian)
    {
        g_calledFunctions.push_back(new CallInfo("sin"));
        ...
    }

    double atan2(double y, double x)
    {
        g_calledFunctions.push_back(new CallInfo("atan2"));
        ...
    }
    
}

#define CALL_INFO_PREDICATE(functionName) [] (CallInfo* info) -> bool\
{\
    static_assert_function_exists(mymath::functionName);/* << how to make this work? */\
    return info->m_function == #functionName;\
}

int main ()
{
    mymath::sin(1);
    mymath::atan2(3, 7);

    auto pos = std::find_if(g_calledFunctions.begin(), g_calledFunctions.end(), CALL_INFO_PREDICATE(sin)); // compiles; function sin exists in mymath

    auto pos2 = std::find_if(g_calledFunctions.begin(), g_calledFunctions.end(), CALL_INFO_PREDICATE(cos)); // produces compile time error, since there is no function named cos in mymath

    ...
}

假设没有重载,您可以直接使用它:

#define CALL_INFO_PREDICATE(functionName) [] (CallInfo* info) -> bool \
{ \
    static_cast<void>(&mymath::functionName); \
    return info->m_function == #functionName; \
}

转换为 void 以避免对未使用的表达式发出警告。

为什么不将函数指针存储在 CallInfo 中并消除对宏的需要?

struct CallInfo
{
    const std::string m_function;
    void* m_function_ptr;
    CallInfo(const std::string& function, void* function_ptr)
        : m_function(function),
          m_function_ptr(function_ptr)
    {
    }
}

std::vector<CallInfo*> g_calledFunctions;

namespace mymath
{

    // all functions with same return type, but differnent parameter lists

    double sin(double radian)
    {
        g_calledFunctions.push_back(new CallInfo("sin", sin));
        ...
    }

    double atan2(double y, double x)
    {
        g_calledFunctions.push_back(new CallInfo("atan2", atan2));
        ...
    }
    
}

int main ()
{
    mymath::sin(1);
    mymath::atan2(3, 7);

    auto pos = std::find_if(g_calledFunctions.begin(), g_calledFunctions.end(), [](CallInfo* info) { return info->m_function_ptr == &mymath::sin; });

    auto pos2 = std::find_if(g_calledFunctions.begin(), g_calledFunctions.end(), [](CallInfo* info) { return info->m_function_ptr == &mymath::cos; });

    // ...
}

现在编译器可以自动为您检查该函数是否存在。