【问题标题】:Select global scope function at compile time在编译时选择全局范围函数
【发布时间】:2018-01-15 21:55:40
【问题描述】:

我必须使用不提供任何关于其版本的编译时间信息的第三方 SDK。

假设 SDK 的 v1 定义了以下功能:

bool func1(int);
bool func2(float) {return false; /* not implemented */}

虽然 SDK 的 v2 已弃用并删除了 func1() 并正确实施了 func2()。我需要使我的代码能够正确编译和使用两个版本的 SDK。如果是v1,则选择func1(),如果不是,则使用func2()

我已经成功实现了编译时查询全局作用域func1()是否存在:

constexpr bool hasFunc1();

我尝试使用标签调度和模板专业化来选择合适的函数。例如:

template <bool THasFunc1>
struct ExecCode;

template<>
struct ExecCode<true>
{
    bool getValue() {
         return func1(123);
    }
}

template<>
struct ExecCode<false>
{
    bool getValue() {
         return func2(123.567);
    }
}

bool getValue() {
    return ExecCode<hasFunc1()>::getValue();
}

但是,编译器 (GCC) 在使用 SDK 的 v2 进行编译时仍然会报告错误func1 has not been declared。为什么它甚至尝试编译不存在的变体?有没有办法允许从 global 范围内选择所描述的功能?

【问题讨论】:

  • 使用#ifdef 可能会更好地解决这个问题,并且you 使用-D 命令行开关提供正确的版本。这就是宏的用途。
  • 如果 GCC 指向 ExecCode&lt;true&gt; 模板特化,它应该有一个 required from here: 行告诉你它为什么认为它需要它。你能发布完整的错误信息吗?

标签: c++ c++11


【解决方案1】:

您遇到了一个问题,您调用一个未声明的函数,其参数不依赖于模板参数。如果 GCC 仍以许可模式支持,则不推荐使用。本质上,编译器试图将getValue() 的第一个实现添加到带有参数"false" 的模板中。可能的解决方法是在getValue()#ifdef 中使用单一模板规范和if constexpr

【讨论】:

  • 我想你是对的。但是,我坚持使用 C++11(不是 14 或 17)。有什么方法可以编译我的代码 SDK 版本不可知论,而无需任何额外的定义,也无需修补 SDK 标头?您能想出一种仅使用语言功能(例如模板)来实现我需要的方法吗?
【解决方案2】:

您的问题也可以在不分派标签的情况下解决。

#include <iostream>

#if !defined(NEW_VERSION)
bool func1(int)   { std::cout << "Implemented" << std::endl;     return true;  }
bool func2(float) { std::cout << "Not implemented" << std::endl; return false; }
#else
bool func2(float) { std::cout << "Implemented" << std::endl;     return true;  }
#endif

namespace workaround {
struct null_type {};

template<typename T = null_type>
bool func1(int a, T t = T()) { return func2((float) a); }
}

void universal_implementation() {
    using namespace workaround;
    func1(123);
}

int main() { universal_implementation(); return 0; }

当声明func1 时,workaround::func1(int, workaround::null_type) 的优先级将低于原始函数。

【讨论】:

  • 您的回答让我找到了正确的方向,谢谢。
猜你喜欢
  • 2021-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
相关资源
最近更新 更多