Template Specialization VS Function Overloading

泄露秘密 提交于 2019-11-26 01:46:50

问题


A textbook I have notes that you can provide your own implementation for standard library functions like swap(x,y) via template specialization or function overloading. This would be useful for any types which can benefit from something other than an assignment swap, like STL containers for example (which already have swaps written, I know).

My questions are the following:

  1. What\'s better: template specialization to give your specialized swap implementation, or function overloading providing the exact parameters you wish to use without a template?

  2. Why is it better? Or if they\'re equal, why is this?


回答1:


Short story: overload when you can, specialise when you need to.

Long story: C++ treats specialisation and overloads very differently. This is best explained with an example.

template <typename T> void foo(T);
template <typename T> void foo(T*); // overload of foo(T)
template <>           void foo<int>(int*); // specialisation of foo(T*)

foo(new int); // calls foo<int>(int*);

Now let's swap the last two.

template <typename T> void foo(T);
template <>           void foo<int*>(int*); // specialisation of foo(T)
template <typename T> void foo(T*); // overload of foo(T)

foo(new int); // calls foo(T*) !!!

The compiler does overload resolution before it even looks at specialisations. So, in both cases, overload resolution chooses foo(T*). However, only in the first case does it find foo<int*>(int*) because in the second case the int* specialisation is a specialisation of foo(T), not foo(T*).


You mentioned std::swap. This makes things even more complicated.

The standard says that you can add specialisations to the std namespace. Great, so you have some Foo type and it has a performant swap then you just specialise swap(Foo&, Foo&) in the std namespace. No problems.

But what if Foo is a template class? C++ doesn't have partial specialisation of functions, so you can't specialise swap. Your only choice is overloading, but the standard says that you aren't allowed to add overloads into the std namespace!

You have two options at this point:

  1. Create a swap(Foo<T>&, Foo<T>&) function in your own namespace, and hope that it gets found via ADL. I say "hope" because if the standard library calls swap like std::swap(a, b); then ADL simply won't work.

  2. Ignore the part of the standard that says not to add overloads and do it anyway. Honestly, even though it's technically not allowed, in all realistic scenarios it's going to work.

One thing to remember though is that there's no guarantee that the standard library uses swap at all. Most algorithms use std::iter_swap and in some implementations that I've looked at, it doesn't always forward to std::swap.




回答2:


There's little to add to Peter Alexander's answer. Let me just mention one use in wich function specialization could be prefearable over overloading: if you have to select among functions with no parameters.

E.g.

template<class T> T zero();
template<> int zero() { return 0; }
template<> long zero() { return 0L; }

To do something similar using function overloading, you would have to add a parameter to the function signature:

int zero(int) { return 0; }
long zero(long) { return 0L; }



回答3:


You aren't allowed to overload functions in the std namespace, but you are allowed to specialize templates (as I recall), so that's one option.

The other option is to put your swap function in the same namespace as the thing it's operating on and using std::swap; before calling an unqualified swap.



来源:https://stackoverflow.com/questions/7108033/template-specialization-vs-function-overloading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!