Is there provision specifying the restriction on "return type" in a function template explicit specialization?
Asked Answered
S

2

18
template<class T>
void fun(T){}

template<>
int fun(int){return 0;}

Consider this example, it is rejected by all implementations. However, I haven't found any persuasive provision in the current standard that specifies this explicit specialization declaration is ill-formed. If it exists, what is the rule?

In addition, the potential relevant rule may be that [temp.deduct.decl#2]

If, for the set of function templates so considered, there is either no match or more than one match after partial ordering has been considered ([temp.func.order]), deduction fails and, in the declaration cases, the program is ill-formed.

I think the meaning of "match" is not sufficiently clear here since "match" didn't clearly define anything.

Stammel answered 22/12, 2021 at 11:32 Comment(3)
If this was allowed, what would static_cast<void(*)(int)>(&fun) do? The compiler would successfully deduce T = int first, then find the specialization, and then it would have to compare the type of the specialized function against the type in the cast?Accustomed
@HolyBlackCat: Good question, but that is another question. (Specifically, see 13.10.3.3 Deducing template arguments taking the address of a function template).Fuddyduddy
@Accustomed The subject of this issue is to find out the relevant provision that can be persuasive to prove this example is ill-formed. If that provision didn't exist, or it is vague, we can consider this is a defect.Stammel
P
6

Your template definition did not match, as void fun(T) is not T fun(T) in your specialization or maybe the other way around if you have int fun(T) to specialize with int fun(int).

You simply have to change to:

template<class T>
T fun(T){}

template<>
int fun(int){}

BTW: All this results in a lot of warning because you did not return anything :-)

Why it did not match:

template<class T>
void fun(T) {}

expands for T=int to:

template<class T>
void fun(int) {}

BUT: the specialization ( it isn't one, because it did not match )

template <>
int fun(int){return 0;}

has a return type which can never deduced from the original template definition, as this, it is never a specialization because it always has return type void while your specialization has int.

Passementerie answered 22/12, 2021 at 11:44 Comment(8)
I omitted to write the return statement. I have fixed the typo. BTW, I just ask for the formal quote instead of how to make the program work. Thanks.Stammel
@Stammel You need a ref to c++ docs where to find that void x() is different from int x()? Really?Passementerie
Not exact. template explicit specialization is a bit different from int x(). The standard is clear about the variance between void x() and int x() but it does not apply to int x<int>()(specialization).Stammel
@xmh0511: I believe you did not catch your typo :-) I added it hopefully a bit clearer in my answer. The definition of your template simply can for no T expand to your specialization, the only case this can work is for void. But that is not what you wrote. If you simply write for every T in your template an int, you have a different thing as your specialization. Simply that!Passementerie
@Passementerie but where in the Standard ([language-lawyer] in the tags) does it say that a template function specialisation has to have the same same return type as the un-specialised version ?Parapet
Again, this question is tagged with language-lawyer. The answer is just your interpretation not of the standard.Stammel
@RichardCritten: Maybe my english is to bad. But again: If you write a specialization, the given template must be able to fit in the form of the original template. But there is no way, to create the specialization out of the given template because the original template ALWAYS RETURN VOID, the specialization returns INT! That never matches! If you make the return type also a template parameter so that the original template CAN RETURN different type, than it works. But you have defined void and only void. The return value is not "variable" as it is written as a fixed one.Passementerie
@Passementerie I know that and the OP knows that - OP is asking where in the C++ Standard ([language-lawyer] tag) it says that, ie OP wants a reference to the C++ Standard as part of the answer.Parapet
F
5

You're on the right track with your quote. Let's also consider the following text:

In all these cases, P is the type of the function template being considered as a potential match and A is ... the function type from the declaration ... The deduction is done as described in [temp.deduct.type].

What are these P and A types? From [temp.deduct.type]

an attempt is made to find template argument values that will make P, after substitution of the deduced values (call it the deduced A), compatible with A.

There's just no value of T that will make A = int fun(int) compatible with P = void fun(T).

Fuddyduddy answered 22/12, 2021 at 20:45 Comment(5)
The answer is reasonable. I would argue that [temp.expl.spec] lacks a reference to [temp.deduct.decl] for general except that [temp.expl.spec] p10 mentions the reference. [temp.expl.spec] p10 is not suitable for template<> void fun<int>(int). BTW, [temp.deduct.type] p10 lack the utterance for deducing function type's return type with form T.Stammel
[temp.deduct.type] p3 mentions that function type deduction includes the return type, for what it's worth.Confectioner
@JeffGarrett However, in [temp.deduct.type] p9, p10, they only specify the form <T> and (T) rather than T. Specifically, [temp.deduct.type] p9 only says:*then each parameter type...*, it didn't mention return type.Stammel
Sure, but it doesn't say it doesn't include the return type. p3-5 are normative and say return types are among the types that compose a function type (p3), that such types participate in deduction (p4), except for a specific list of contexts (p5) which aren't applicable as far as I see.Confectioner
@JeffGarrett Well, I would expect that [temp.deduct.type] can cover the complete story about type deduction, such as a single template parameter vs. a compound actual type.Stammel

© 2022 - 2024 — McMap. All rights reserved.