Leaving aside the policy and semantic issues of whether you should specialize a function template from the std
namespace,
The following snippet does not work:
class stackiterator {};
struct stack { stackiterator Begin() { return stackiterator{};} };
#include <iterator>
namespace std
{
template <> stackiterator begin<stack>(stack& S)
{
return S.Begin();
}
}
However, the following snippet works just fine:
class stackiterator {};
struct stack { stackiterator begin() { return stackiterator{};} };
#include <iterator>
namespace std
{
template <> stackiterator begin<stack>(stack& S)
{
return S.begin();
}
}
The key difference is the presence of Begin()
vs begin()
as a member function of stack
. std::begin()
is defined as:
template <class C> auto begin(C& c) -> decltype(c.begin());
template <class C> auto begin(const C& c) -> decltype(c.begin());
When you specialize a function template, you must still keep the return type the same. When you don't have begin()
as a member of Stack
, the compiler does not know how to determine the return type.
That is the reason for error produced by the compiler.
BTW, there is another SO post that partially answers what can be specialized and what can't be specialized.
Looking at the part of the standard that deals with std::begin()
, Section 24.3, I don't see anything about not being able to specialize std::begin()
.
stack::begin()
and just use the implementation ofstd::begin()
as is? – Rockawaybegin
that is found by ADL. You shouldn't really be writingstd::begin(stuff)
anyway. – Uproarstd::begin
because [see my previous comment]. – Motorbusstd::begin(stuff)
? – Motorbusfor
, for instance; and because it's impossible; specializing a function template can't change the return type, and the one you want to specialize returns "whatever memberbegin()
returns", which obviously won't work if you don't have a memberbegin()
. – Uproarbegin
functions through ADL. It's messy and Eric Niebler proposed a solution to makestd::begin
(and other customization points) do all that so that we don't end up having a repetitive bunch of using statements at the top of functions that grows larger as the list of customization points grows. – Proliferatestd::begin()
to make it work with range-basedfor
. Oh and I didn't know that specializations can't change return types, thanks. – Motorbus