在编译时选择全局范围函数

时间:2018-01-15 06:11:09

标签: c++ c++11

我必须使用第三方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。为什么它甚至尝试编译不存在的变体?有没有办法允许从全局范围中选择功能?

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

您的问题也可以在没有标签调度的情况下解决。

#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)的优先级将低于原始功能。