我必须使用第三方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
。为什么它甚至尝试编译不存在的变体?有没有办法允许从全局范围中选择功能?
答案 0 :(得分:2)
您遇到的问题是使用不依赖于模板参数的参数调用未声明的函数。如果GCC仍然支持宽松模式,则不推荐使用。本质上,编译器尝试将getValue()
的第一个实现添加到带有参数"false"
的模板中。可能的解决方法是在if constexpr
或getValue()
中使用单个模板规范和#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)
的优先级将低于原始功能。