【问题标题】:What is the difference between function overloading and template function? Which is more appropriate? [closed]函数重载和模板函数有什么区别?哪个更合适? [关闭]
【发布时间】:2019-09-23 11:30:34
【问题描述】:
template<>std::string Add(std::string x ,std::string y)
{
    return x.append(y);
}

std::string Add(std::string x ,std::string y)
{
    return x.append(y);
}

如果我们可以使用函数重载来特化代码,为什么还需要模板特化?

【问题讨论】:

  • 这真的取决于设计和用例,没有一个“真正”的答案。
  • 当超载可以做到的时候,那就去超载,但这只是我个人的看法
  • 如果您有 10 种类型需要完全相同的调用而两种不需要。你是在写 12 个重载还是 1 个模板和 2 个特化?我更喜欢模板
  • @deW1 我在询问这两个专业化。我们可以使用模板进行专业化std::string Add(std::string x ,std::string y) { return x.append(y ); } 但我们也可以专门使用函数重载 .right std::string Add(std::string x ,std::string y) { return x.append(y); }
  • @deW1 我认为您的(修辞?)问题的答案并不那么明显。如果我想阻止第 13 种类型作为参数传递,我更喜欢重载而不是模板 vodoo(尽管我仍然是一个 c++11 的人,其中 sfinae 仍然比现在更加神秘)

标签: c++ templates overloading template-specialization


【解决方案1】:

如果我们可以使用函数重载来专门化代码。为什么需要模板专门化

因为不同的事物有不同的行为。

一个实际的例子。

下面的例子编译链接没有问题

#include <string>

void foo (std::string const &)
 { }

int main ()
 {
   foo("abc");
 }

注意"abc" 可以转换为std::string,但不是std::string(是char const [4])。

因此,调用常规(非模板)函数时,参数会在必要时进行转换。

观察以下代码

#include <string>

template <typename T>
void foo (T const &);

template <>
void foo (std::string const &)
 { }

int main ()
 {
   foo("abc");
 }

现在代码编译但不链接:foo() 是一个模板(仅声明)模板函数,仅定义了 std::string 完全特化。

这一次,编译器推断参数的类型(char const [4],不同于std::string)因此给出了一个线性错误,因为没有定义foo() 的通用版本。

这样你可以强制foo() 只能用std::string 调用,而不是可以转换为std::string 的值。

你可以得到同样的东西,混合重载和模板,得到一个编译(不链接)错误如下

#include <string>

template <typename T>
void foo (T const &) = delete;

void foo (std::string const &)
 { }

int main ()
 {
   foo("abc");
 }

现在非模板foo() 可以(理论上)接受char cont [4],但被声明(并删除)模板版本。因此,再次假设char const [4] 不是std::string,编译器会优先考虑模板版本。即被删除。所以编译错误。

【讨论】:

    【解决方案2】:

    因为根据用例,您有时会编写通用的容器/函数,即它们适用于每种类型。例如std::vector。但是,当您执行std::vector&lt;string&gt; 和std::vector&lt;const char*&gt;(虽然都表示字符串)时,向量的含义并不相同,因为一个存储字符串,另一个存储指向空终止字符串的指针。那么,您将如何从设计的角度来解决这个问题呢?

    好吧,你要么忽略这种类型的问题,要么阻止使用这种类型,或者编写一个专门化,使这个容器针对这种类型以不同的方式工作,以达到你的设计目的。同样,根据您要解决的问题,为您的函数编写专业化。

    因此,这些模板专业化是为了解决特定类型的问题。如果您不需要它,请不要使用它。您无需无缘无故地使代码复杂化。

    【讨论】:

      【解决方案3】:

      这取决于用例。 考虑一个函数 Add(),它排除两个变量并返回总和。现在基于一个用例,这两个变量可以是整数或浮点数。这可以通过以下两种方式实现:

      Template <typename T>
      T Add(T x, T y)
      {
          return x + y;
      }
      

      或者,您可以分别编写两个函数。一个用于整数,一个用于浮点参数。

      int Add(int x, int y)
      {
          return x + y;
      }
      

      和,

      float Add(float x, float y)
      {
           return x + y;
      }
      

      【讨论】:

        猜你喜欢
        • 2010-11-10
        • 2011-03-24
        • 2018-10-24
        • 1970-01-01
        • 2015-03-15
        • 1970-01-01
        • 2021-02-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多