【问题标题】:'Overloading' function without input parameters based on template types基于模板类型的无输入参数的“重载”功能
【发布时间】:2021-02-28 10:53:50
【问题描述】:

我开始使用模板,遇到了需要调用基于 2 种模板参数类型的函数的问题。我正在编写简单的单元库,它将具有帮助器 getConvertionFactor 函数,这些函数将定义单元之间的比率。我希望能够根据作为参数传递的类型在模板运算符 +、-、*、/ 定义中拾取一个函数。我知道当这些参数进一步传递给getConvertionFactor 函数时,这是可能的。然后重载决议将拾取在给定参数类型之间具有指定比率的函数。但是我不明白这种方法会导致不必要地将 LHS 和 RHS 参数复制到 getConvertionFactor 函数中,只是为了执行重载解决方案。我想避免它并以某种方式基于 2 种类型查找函数,而无需将 dummy 参数传递给它。

#include <iostream>

struct Kilometer {
    int val = 0;
};
struct NauticalMile {
    int val = 0;
};

template<class FromType, class ToType>
double getConvertionFactor() {
    return FromType::getBaseValue();
}

// How to define such conceptually function pointer lookup based on these 2 types?
// double getConvertionFactor<Kilometer, NauticalMile>() {
//     return 0.1;
// }

// Works but requires copying parameters
double getConvertionFactor(Kilometer km, NauticalMile /*nm*/) {
    return 0.1 * km.val;
}

template<class LHS_Unit, class RHS_Unit>
LHS_Unit operator+(const LHS_Unit& nm, const RHS_Unit& km) {
    LHS_Unit lhs;
    lhs.val = nm.val + getConvertionFactor(nm, km)*km.val;
    return lhs;
}

int main() {
    Kilometer km{100};
    NauticalMile nm{100};

    auto res = km + nm;
    std::cout << res.val << std::endl;

    return 0;
}   

【问题讨论】:

  • 附带说明,小型 POD 类型最好按值传递,而不是按引用传递。

标签: c++ templates c++17


【解决方案1】:

你可以这样做:

template<class FromType, class ToType>
double getConvertionFactor() {
    return 1;
}

template<>
double getConvertionFactor<Kilometer, NauticalMile>() {
    return 1.852;
}

template<>
double getConvertionFactor<NauticalMile, Kilometer>() {
    return 1 / 1.852;
}

template<class LHS_Unit, class RHS_Unit>
LHS_Unit operator+(const LHS_Unit& lhs, const RHS_Unit& rhs) {
    return { lhs.val + getConvertionFactor<LHS_Unit, RHS_Unit>() * rhs.val };
}

但实现用户定义的转换运算符可能是一个好主意,以便类型可以隐式地相互转换。

#include <iostream>

struct Kilometer;
struct NauticalMile;

struct Kilometer {
    double val = 0;

    operator NauticalMile() const;
};
struct NauticalMile {
    double val = 0;

    operator Kilometer() const;
};

Kilometer::operator NauticalMile() const {
    return { val / 1.852 };
}

NauticalMile::operator Kilometer() const {
    return { val * 1.852 };
}

template<class LHS_Unit, class RHS_Unit>
LHS_Unit operator+(const LHS_Unit& lhs, const RHS_Unit& rhs) {
    return { lhs.val + static_cast<LHS_Unit>(rhs).val };
}

int main() {
    Kilometer km{ 100 };
    NauticalMile nm{ 100 };

    auto res = km + nm;
    std::cout << res.val << std::endl;

    return 0;
}

【讨论】:

  • 为每种类型定义一个转换运算符到指定的公共单位是有意义的。
  • 是的,为内部表示选择一些“通用单位”(公里或英里)并在该单位中执行所有计算可能会更容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-25
相关资源
最近更新 更多