【问题标题】:Is it ok to return integer from template function?从模板函数返回整数可以吗?
【发布时间】:2011-11-15 10:17:37
【问题描述】:

我想写一个符号函数模板。我是这样做的:

template<class T> T sign(const T &value)
{
    if (value > 0) return 1;
    else if (value < 0) return -1;
    return 0;
}

它正在工作,但我不确定当我的函数实际上应该返回 T 时返回一个数值是否好。这个函数好吗?

【问题讨论】:

  • 您依赖于隐式转换 - 这可能很危险,除非您了解所有类型的 T 确切行为。
  • 是的,这可能很危险,但这似乎正是预期的行为 - 符号是相同类型的 -1/0/1。
  • 您可能应该返回一个int,因为它可能比您的 T 更有效(想象一下,如果 T 是一个多预定义的 bignum)。或者您可以使用enum { Negative=-1, Zero=0, Positive=+1 } 甚至(如果是 C++11)枚举类。

标签: c++ templates function


【解决方案1】:

不,T 可能是没有从整数转换的类型。

在这种情况下,它会在编译时失败。

如果您希望它设计为整数,请声明它。

template<class T> int sign(const T &value)
{
    if (value > 0) return 1;
    else if (value < 0) return -1;
    return 0;
}

【讨论】:

    【解决方案2】:

    只有从 intT 的隐式转换,您的函数才会编译。如果这是你的意图,那没关系,但它看起来并不好。

    我认为最好重写代码以返回T,也许使用类似:

    //return T(0);
    return static_cast<T>(0); // Better alternative as suggested by Steve Jessop
    

    这会从 int 显式构造一个 T。但请注意,如果有人使用可以从 int 构造的 T 调用此方法,它将起作用 - 无论该构造函数的真正含义是什么。

    【讨论】:

    • 关于“注意”,static_cast&lt;T&gt;(0) 可能更安全一些。它排除了void*,而您建议的 C 风格演员则没有。
    【解决方案3】:

    你使用 T 作为返回类型有什么原因吗?您应该考虑将其更改为某个整数或enum{USINGNED,ZERO,SIGNED}。在这种情况下,只要 T 具有重载运算符 &gt;&lt;,您的函数就可以工作。

    【讨论】:

      【解决方案4】:

      只要您可以将 -1/0/1 转换为 T,这正是将会发生的事情。我相信你想要实现的是与输入具有相同类型的符号,所以你唯一能做的就是添加显式强制转换,这几乎没有什么区别——正如史蒂夫在 cmets 中指出的那样,它会根据 T显式构造函数。

      【讨论】:

      • 如果T 有一个explicit 构造函数采用int,是否有演员表会有所不同。
      • 嗯,没错。现在的问题是它是好是坏,我会将您的评论添加到我的答案中,并让 OP 决定。
      • 同意,提问者必须做出决定。他是否希望模板对于 int 可以显式转换但不能隐式转换的类型失败?例如,vector 有一个到int 的显式转换,因为它有一个显式构造函数,它接受size_type,如果传递-1,它可能会失败。这个模板无论如何都不会为vector 实例化,因为vector 没有&lt;&gt;int 的比较,但它是对你应该期望演员做的那种事情的警告。再举一个例子,int 可以转换为 void*
      【解决方案5】:

      我认为这很好,因为 T 将是您想要找出符号的数字。 让我们看看调用者函数。

      double x = -5.2;
      int ret = sign(x);
      

      在最后一条语句中,sign 将返回 int 常量,该常量将分配给 ret(如果需要,则进行隐式类型转换);

      【讨论】:

        猜你喜欢
        • 2013-11-02
        • 1970-01-01
        • 2020-06-16
        • 1970-01-01
        • 2018-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-19
        相关资源
        最近更新 更多