【问题标题】:overload with typedef gives an error使用 typedef 重载会出错
【发布时间】:2016-08-21 11:37:43
【问题描述】:

考虑以下类型:

#include <iostream>

typedef unsigned long long      usize_t;
typedef unsigned __int16        uword_t;
typedef uword_t                 clockval_t;     // time without seconds in format HHMM

std::string toString(clockval_t nClock)
{
    return std::to_string((usize_t)nClock/100) + ":" + std::to_string((usize_t)nClock % 100);
}

std::string toString(uword_t nValue)
{
    return std::to_string((usize_t)nValue);
}

void test(void)
{
    uword_t val = 1;
    clockval_t time = 1023; // 10:23

    std::cout << "Value: " << toString(val);
    std::cout << "time: " << toString(time);
}

现在当我尝试编译它时,我从编译器收到一个错误,告诉我std::string toString(clockval_t) 已经有一个主体。我当然理解为什么会发生这种情况,因为 typedef 只是 uword_t 的别名。

AFAIK 唯一的解决方案是提供单独的方法:

std::string toClockString(clockval_t);

或者把它变成一个对象:

class clockval ...

这是正确的还是有其他方法可以让编译器选择正确的重载?

【问题讨论】:

  • 啊,C 类型系统的乐趣!
  • 是的,IMO 有点弱,因为 typedefs 的全部意义在于创建新类型,因此编译器应该能够正确区分它们以使其保持一致。我想这涉及到一些向后兼容性问题。

标签: c++ overloading


【解决方案1】:

即使有办法让编译器选择正确的版本,你知道它会很容易出错吗?幸运的是,没有这样的方法,因为typedef 创建了别名,仅此而已。

我建议你把它转换成类。如果您提供适当的构造函数和转换运算符,那么您甚至不需要更改使用clockval_t 的部分代码:

class clockval_t {
public:
  clockval_t(uword_t aValue) : value(aValue) {}
  operator uword_t() const { return value; }

private:
  uword_t value;
};

...

clockval_t time = 1023; // works fine
std::cout << time << std::endl; // works fine
std::cout << (time / 10) << std::endl; // works fine

【讨论】:

  • 谢谢!这绝对是最好的答案。 :) 我检查了机器代码以确保没有不必要的开销,而不是一个简单的单词(这将是我对对象的主要关注点),并且它的行为与 word 完全一样,同时具有类型的好处. :)
  • 这有一个缺点,即您将丢失clockval_t 上的所有算术运算。您需要重新定义类中的每个运算符(如果需要)。
【解决方案2】:

这是正确的还是有其他方法可以让编译器选择正确的重载?

是的,你是对的,你不能在 typedef 上重载,因为它只是一个别名。正如您正确建议的那样,重命名函数或使用class 创建新类型。添加 fake 参数只是为了更改函数签名通常是一个坏主意,重命名更清晰。

【讨论】:

    【解决方案3】:

    typedef的含义在标准中定义为(7.1.3 The typedef specifier):

    在其声明范围内,typedef-name 在语法上等同于关键字,并命名与标识符 (...) 关联的类型。因此 typedef-name 是另一种类型的同义词。一个 typedef-name 确实 不引入新类型(...)。

    因此,这两个函数在输入参数的类型上确实是模棱两可的。您需要区分类型(例如,通过使用不同的类型,例如类或枚举),或者可能添加第二个参数(可能带有默认值)指示传入的确切类型。

    原始答案链接:https://softwareengineering.stackexchange.com/questions/254473/in-which-stage-of-compilation-is-typedef-resolved-by-the-compiler

    【讨论】:

    • 我喜欢这个答案,因为引用,但我同意接受的答案,即添加假参数不是一个好主意,本质上与创建特定函数名称非常相似。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    相关资源
    最近更新 更多