在模板参数的函数中使用一个命名空间或另一个命名空间

Use one namespace or another in function of a template parameter

本文关键字:命名空间 一个 另一个 参数 函数      更新时间:2023-10-16

我想在某些情况下使用std::pow(从cmath(的实现,而在其他情况下,我想使用myspace::pow

namespace myspace
{
template <typename T>
T pow(T val, unsigned exp)
{
if (exp == 0) return 1;
return val*pow(val,exp-1);
}
}

不同的事例由模板参数确定。

template <typename T>
void myFunction()
{
auto val = pow(2.1,3);
/* ... */
}

如果T == double,我希望用std::pow计算val。如果T == mydouble,我希望用myspace::pow计算val。现在,我有很多像auto val = pow(2.1,3);这样的行,我想避免检查每行代码的T类型。

struct mydouble { /* ... */ };
myFunction<double>(); // uses std::pow
myFunction<mydouble>(); // uses myspace::pow

我一直在为此摸不着头脑,但我找不到解决方案。有什么建议吗?

我可以建议几种解决方案。


类调度程序 (C++11(

只需实现一个函子,该函子根据其模板化类型选择正确的实现:

template <typename T>
struct PowerAdapter {
auto operator()(const T& arg, const T& exp) const {
return std::pow(arg, exp);
}
};
template <>
struct PowerAdapter<myspace::MyDouble> {
auto operator()(const myspace::MyDouble& arg, unsigned exp) const {
return myspace::pow(arg, exp);
} 
};

您可以按如下方式使用它:

template <typename T>
void myFunction(const T& t) {
using Pow = PowerAdapter<T>;
auto val = Pow{}(t, t);
// ...
}

完整的代码示例


依赖于参数的查找 (C++98(

如果您的类MyDouble位于pow的同一命名空间中,则可以使用以下C++规则:

除了通常的非限定名称查找所考虑的范围和命名空间之外,还在其参数的命名空间中查找函数名称

所以代码:

template <typename T>
void myFunction(const T& t) {
pow(t, 12);
}

将根据T的命名空间选择合适的pow。 请注意,如果出现double,则需要从全局命名空间中的math.h中选择pow(非限定名称查找(。

完整的代码示例

我个人不喜欢这种方法,因为它隐藏了选择机制,而且更难扩展。


if constexpr(C++17(

您可以在编译时选择合适的分支。 将选择逻辑包装到适当的函数(或函子(中。像这样:

template <typename T, typename U>
auto PowerAdapter(const T& val, const U& exp) {
if constexpr (std::is_same_v<T, myspace::MyDouble>) {
return myspace::pow(val, exp);
} else {
return std::pow(val, exp);
}
}

完整的代码示例

使用依赖于参数的查找,您可以轻松实现此目的

namespace ns
{
template <typename T>
auto pow(T val, unsigned exp)
{
using std::pow;
std::cout << __FUNCTION__ << 'n';
return pow(val, exp);
}
}
struct mydouble
{
double d;
};
mydouble pow(mydouble val, unsigned exp)
{
std::cout << __FUNCTION__ << 'n';
return val;
}
int main() 
{
ns::pow(mydouble{ 3.14 }, 2); // runs pow
ns::pow(4, 2);                // runs std::pow
}
相关文章: