Function template overload resolution with two parameter packs












9















Consider the following code:



#include<iostream>

template<class..., class... T>
int f(T...) { return 1; }

template<class... T>
int f(T...) { return 2; }

int main()
{
std::cout << f(1);
}


It compiles and prints 1 on gcc 8.2, but fails to compile on clang 7 because of the call f(1) being ambiguous.



If the call is replaced by f() both compiler fail to compile claiming the call to be ambiguous.



If the parameter packs class... T are replaced with a simple parameter class T (and T... with T), both compiler also claim ambiguity.



Which of the compiler is standard-conform in the first example? I suppose this comes down to the specific partial ordering rules for function templates, or is it already ill-formed to use the double parameter pack in this way?



Edit:



My understanding is that the double pack is itself not ill-formed, because [temp.param] 17.1/15 in my reading seems to explicitly allow this if the second pack is deducible from the function arguments, which seems to be the case because of the T... function parameter pack.



It is also possible to specify the first parameter pack's arguments explicitly, though not the second ones and so it is not always the case that (after template argument deduction) at least one parameter pack is empty. I am not sure whether that makes the program ill-formed, because I don't know how to read e.g. [temp.res] 17.7/8.3 in this context.



Both gcc and clang seem to be fine with the double parameter pack itself, e.g. when the second function template overload is removed, both compiler print 1. But this might be a case of ill-formed, no diagnostic required.



Furthermore I assume that with class template argument deduction, a variadic class template could have a variadic constructor template defined, which would imply a constructor candidate similar to my double parameter pack example and as far as I understand the same overload resolution and template argument deduction takes place in that context. This question was motivated by another question with such a setup: Variadic class template deduction fails with gcc 8.2, compiles with clang and msvc
See also for a discussion on that: Deduction guides and variadic class templates with variadic template constructors - mismatched argument pack lengths



Now I have also found the answer to the question Deduction guide and variadic templates which I assume implies that gcc is wrong and the call should be considered ambiguous, but I would like to have it verified that this applies here the same way. I would also welcome in a bit more detail the reasoning, because the function template partial ordering rules seem very unclear to me.










share|improve this question




















  • 1





    first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?

    – Richard Hodges
    Nov 18 '18 at 8:28











  • @RichardHodges - {} and {int} (or whatever else is passed as function arguments). A pack can be deduced as empty... I think.

    – StoryTeller
    Nov 18 '18 at 8:36











  • @RichardHodges I added some explanation why I it doesn't seem obvious to me that the double pack itself is already ill-formed.

    – user10605163
    Nov 18 '18 at 9:49
















9















Consider the following code:



#include<iostream>

template<class..., class... T>
int f(T...) { return 1; }

template<class... T>
int f(T...) { return 2; }

int main()
{
std::cout << f(1);
}


It compiles and prints 1 on gcc 8.2, but fails to compile on clang 7 because of the call f(1) being ambiguous.



If the call is replaced by f() both compiler fail to compile claiming the call to be ambiguous.



If the parameter packs class... T are replaced with a simple parameter class T (and T... with T), both compiler also claim ambiguity.



Which of the compiler is standard-conform in the first example? I suppose this comes down to the specific partial ordering rules for function templates, or is it already ill-formed to use the double parameter pack in this way?



Edit:



My understanding is that the double pack is itself not ill-formed, because [temp.param] 17.1/15 in my reading seems to explicitly allow this if the second pack is deducible from the function arguments, which seems to be the case because of the T... function parameter pack.



It is also possible to specify the first parameter pack's arguments explicitly, though not the second ones and so it is not always the case that (after template argument deduction) at least one parameter pack is empty. I am not sure whether that makes the program ill-formed, because I don't know how to read e.g. [temp.res] 17.7/8.3 in this context.



Both gcc and clang seem to be fine with the double parameter pack itself, e.g. when the second function template overload is removed, both compiler print 1. But this might be a case of ill-formed, no diagnostic required.



Furthermore I assume that with class template argument deduction, a variadic class template could have a variadic constructor template defined, which would imply a constructor candidate similar to my double parameter pack example and as far as I understand the same overload resolution and template argument deduction takes place in that context. This question was motivated by another question with such a setup: Variadic class template deduction fails with gcc 8.2, compiles with clang and msvc
See also for a discussion on that: Deduction guides and variadic class templates with variadic template constructors - mismatched argument pack lengths



Now I have also found the answer to the question Deduction guide and variadic templates which I assume implies that gcc is wrong and the call should be considered ambiguous, but I would like to have it verified that this applies here the same way. I would also welcome in a bit more detail the reasoning, because the function template partial ordering rules seem very unclear to me.










share|improve this question




















  • 1





    first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?

    – Richard Hodges
    Nov 18 '18 at 8:28











  • @RichardHodges - {} and {int} (or whatever else is passed as function arguments). A pack can be deduced as empty... I think.

    – StoryTeller
    Nov 18 '18 at 8:36











  • @RichardHodges I added some explanation why I it doesn't seem obvious to me that the double pack itself is already ill-formed.

    – user10605163
    Nov 18 '18 at 9:49














9












9








9


3






Consider the following code:



#include<iostream>

template<class..., class... T>
int f(T...) { return 1; }

template<class... T>
int f(T...) { return 2; }

int main()
{
std::cout << f(1);
}


It compiles and prints 1 on gcc 8.2, but fails to compile on clang 7 because of the call f(1) being ambiguous.



If the call is replaced by f() both compiler fail to compile claiming the call to be ambiguous.



If the parameter packs class... T are replaced with a simple parameter class T (and T... with T), both compiler also claim ambiguity.



Which of the compiler is standard-conform in the first example? I suppose this comes down to the specific partial ordering rules for function templates, or is it already ill-formed to use the double parameter pack in this way?



Edit:



My understanding is that the double pack is itself not ill-formed, because [temp.param] 17.1/15 in my reading seems to explicitly allow this if the second pack is deducible from the function arguments, which seems to be the case because of the T... function parameter pack.



It is also possible to specify the first parameter pack's arguments explicitly, though not the second ones and so it is not always the case that (after template argument deduction) at least one parameter pack is empty. I am not sure whether that makes the program ill-formed, because I don't know how to read e.g. [temp.res] 17.7/8.3 in this context.



Both gcc and clang seem to be fine with the double parameter pack itself, e.g. when the second function template overload is removed, both compiler print 1. But this might be a case of ill-formed, no diagnostic required.



Furthermore I assume that with class template argument deduction, a variadic class template could have a variadic constructor template defined, which would imply a constructor candidate similar to my double parameter pack example and as far as I understand the same overload resolution and template argument deduction takes place in that context. This question was motivated by another question with such a setup: Variadic class template deduction fails with gcc 8.2, compiles with clang and msvc
See also for a discussion on that: Deduction guides and variadic class templates with variadic template constructors - mismatched argument pack lengths



Now I have also found the answer to the question Deduction guide and variadic templates which I assume implies that gcc is wrong and the call should be considered ambiguous, but I would like to have it verified that this applies here the same way. I would also welcome in a bit more detail the reasoning, because the function template partial ordering rules seem very unclear to me.










share|improve this question
















Consider the following code:



#include<iostream>

template<class..., class... T>
int f(T...) { return 1; }

template<class... T>
int f(T...) { return 2; }

int main()
{
std::cout << f(1);
}


It compiles and prints 1 on gcc 8.2, but fails to compile on clang 7 because of the call f(1) being ambiguous.



If the call is replaced by f() both compiler fail to compile claiming the call to be ambiguous.



If the parameter packs class... T are replaced with a simple parameter class T (and T... with T), both compiler also claim ambiguity.



Which of the compiler is standard-conform in the first example? I suppose this comes down to the specific partial ordering rules for function templates, or is it already ill-formed to use the double parameter pack in this way?



Edit:



My understanding is that the double pack is itself not ill-formed, because [temp.param] 17.1/15 in my reading seems to explicitly allow this if the second pack is deducible from the function arguments, which seems to be the case because of the T... function parameter pack.



It is also possible to specify the first parameter pack's arguments explicitly, though not the second ones and so it is not always the case that (after template argument deduction) at least one parameter pack is empty. I am not sure whether that makes the program ill-formed, because I don't know how to read e.g. [temp.res] 17.7/8.3 in this context.



Both gcc and clang seem to be fine with the double parameter pack itself, e.g. when the second function template overload is removed, both compiler print 1. But this might be a case of ill-formed, no diagnostic required.



Furthermore I assume that with class template argument deduction, a variadic class template could have a variadic constructor template defined, which would imply a constructor candidate similar to my double parameter pack example and as far as I understand the same overload resolution and template argument deduction takes place in that context. This question was motivated by another question with such a setup: Variadic class template deduction fails with gcc 8.2, compiles with clang and msvc
See also for a discussion on that: Deduction guides and variadic class templates with variadic template constructors - mismatched argument pack lengths



Now I have also found the answer to the question Deduction guide and variadic templates which I assume implies that gcc is wrong and the call should be considered ambiguous, but I would like to have it verified that this applies here the same way. I would also welcome in a bit more detail the reasoning, because the function template partial ordering rules seem very unclear to me.







c++ language-lawyer overload-resolution template-deduction






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 18 '18 at 10:50







user10605163

















asked Nov 18 '18 at 5:27









user10605163user10605163

2,858624




2,858624








  • 1





    first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?

    – Richard Hodges
    Nov 18 '18 at 8:28











  • @RichardHodges - {} and {int} (or whatever else is passed as function arguments). A pack can be deduced as empty... I think.

    – StoryTeller
    Nov 18 '18 at 8:36











  • @RichardHodges I added some explanation why I it doesn't seem obvious to me that the double pack itself is already ill-formed.

    – user10605163
    Nov 18 '18 at 9:49














  • 1





    first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?

    – Richard Hodges
    Nov 18 '18 at 8:28











  • @RichardHodges - {} and {int} (or whatever else is passed as function arguments). A pack can be deduced as empty... I think.

    – StoryTeller
    Nov 18 '18 at 8:36











  • @RichardHodges I added some explanation why I it doesn't seem obvious to me that the double pack itself is already ill-formed.

    – user10605163
    Nov 18 '18 at 9:49








1




1





first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?

– Richard Hodges
Nov 18 '18 at 8:28





first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?

– Richard Hodges
Nov 18 '18 at 8:28













@RichardHodges - {} and {int} (or whatever else is passed as function arguments). A pack can be deduced as empty... I think.

– StoryTeller
Nov 18 '18 at 8:36





@RichardHodges - {} and {int} (or whatever else is passed as function arguments). A pack can be deduced as empty... I think.

– StoryTeller
Nov 18 '18 at 8:36













@RichardHodges I added some explanation why I it doesn't seem obvious to me that the double pack itself is already ill-formed.

– user10605163
Nov 18 '18 at 9:49





@RichardHodges I added some explanation why I it doesn't seem obvious to me that the double pack itself is already ill-formed.

– user10605163
Nov 18 '18 at 9:49












1 Answer
1






active

oldest

votes


















6














There are two issues here.





First, [temp.deduct.partial]/12 (I also quote the example since it is similar to yours) says:




In most cases, deduction fails if not all template parameters have values, but for partial ordering purposes a template parameter may remain without a value provided it is not used in the types being used for partial ordering. [ Note: A template parameter used in a non-deduced context is considered used. — end note ] [ Example:



template <class T> T f(int);            // #1
template <class T, class U> T f(U); // #2
void g() {
f<int>(1); // calls #1
}


— end example ]




The types being used for partial ordering are T... according to [temp.deduct.partial]/3:




The types used to determine the ordering depend on the context in which the partial ordering is done:




  • In the context of a function call, the types used are those function parameter types for which the function call has arguments.


  • ...





So the first unnamed template parameter pack class... does not affect the result of partial ordering. Since there are no other differences for the two function templates, neither is more specialized than the other, resulting an ambiguous call.



This may be related to bug 49505 of GCC.





Second, even though the second function template does not exist, the call should still be ill-formed. According to [temp.arg.explicit]/3:




... A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments ...




Only trailing template parameter pack can be deduced to an empty pack, while the first unnamed template parameter pack class... is not a trailing template parameter pack.



Both GCC (bug 69623) and Clang (bug 26435) have bugs for this issue.






share|improve this answer





















  • 1





    See also stackoverflow.com/a/41069348/1639256

    – Oktalist
    Nov 18 '18 at 16:53











  • @Oktalist That's a different issue. That issue is fixed by an editorial change.

    – xskxzr
    Nov 18 '18 at 17:20











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53358165%2ffunction-template-overload-resolution-with-two-parameter-packs%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









6














There are two issues here.





First, [temp.deduct.partial]/12 (I also quote the example since it is similar to yours) says:




In most cases, deduction fails if not all template parameters have values, but for partial ordering purposes a template parameter may remain without a value provided it is not used in the types being used for partial ordering. [ Note: A template parameter used in a non-deduced context is considered used. — end note ] [ Example:



template <class T> T f(int);            // #1
template <class T, class U> T f(U); // #2
void g() {
f<int>(1); // calls #1
}


— end example ]




The types being used for partial ordering are T... according to [temp.deduct.partial]/3:




The types used to determine the ordering depend on the context in which the partial ordering is done:




  • In the context of a function call, the types used are those function parameter types for which the function call has arguments.


  • ...





So the first unnamed template parameter pack class... does not affect the result of partial ordering. Since there are no other differences for the two function templates, neither is more specialized than the other, resulting an ambiguous call.



This may be related to bug 49505 of GCC.





Second, even though the second function template does not exist, the call should still be ill-formed. According to [temp.arg.explicit]/3:




... A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments ...




Only trailing template parameter pack can be deduced to an empty pack, while the first unnamed template parameter pack class... is not a trailing template parameter pack.



Both GCC (bug 69623) and Clang (bug 26435) have bugs for this issue.






share|improve this answer





















  • 1





    See also stackoverflow.com/a/41069348/1639256

    – Oktalist
    Nov 18 '18 at 16:53











  • @Oktalist That's a different issue. That issue is fixed by an editorial change.

    – xskxzr
    Nov 18 '18 at 17:20
















6














There are two issues here.





First, [temp.deduct.partial]/12 (I also quote the example since it is similar to yours) says:




In most cases, deduction fails if not all template parameters have values, but for partial ordering purposes a template parameter may remain without a value provided it is not used in the types being used for partial ordering. [ Note: A template parameter used in a non-deduced context is considered used. — end note ] [ Example:



template <class T> T f(int);            // #1
template <class T, class U> T f(U); // #2
void g() {
f<int>(1); // calls #1
}


— end example ]




The types being used for partial ordering are T... according to [temp.deduct.partial]/3:




The types used to determine the ordering depend on the context in which the partial ordering is done:




  • In the context of a function call, the types used are those function parameter types for which the function call has arguments.


  • ...





So the first unnamed template parameter pack class... does not affect the result of partial ordering. Since there are no other differences for the two function templates, neither is more specialized than the other, resulting an ambiguous call.



This may be related to bug 49505 of GCC.





Second, even though the second function template does not exist, the call should still be ill-formed. According to [temp.arg.explicit]/3:




... A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments ...




Only trailing template parameter pack can be deduced to an empty pack, while the first unnamed template parameter pack class... is not a trailing template parameter pack.



Both GCC (bug 69623) and Clang (bug 26435) have bugs for this issue.






share|improve this answer





















  • 1





    See also stackoverflow.com/a/41069348/1639256

    – Oktalist
    Nov 18 '18 at 16:53











  • @Oktalist That's a different issue. That issue is fixed by an editorial change.

    – xskxzr
    Nov 18 '18 at 17:20














6












6








6







There are two issues here.





First, [temp.deduct.partial]/12 (I also quote the example since it is similar to yours) says:




In most cases, deduction fails if not all template parameters have values, but for partial ordering purposes a template parameter may remain without a value provided it is not used in the types being used for partial ordering. [ Note: A template parameter used in a non-deduced context is considered used. — end note ] [ Example:



template <class T> T f(int);            // #1
template <class T, class U> T f(U); // #2
void g() {
f<int>(1); // calls #1
}


— end example ]




The types being used for partial ordering are T... according to [temp.deduct.partial]/3:




The types used to determine the ordering depend on the context in which the partial ordering is done:




  • In the context of a function call, the types used are those function parameter types for which the function call has arguments.


  • ...





So the first unnamed template parameter pack class... does not affect the result of partial ordering. Since there are no other differences for the two function templates, neither is more specialized than the other, resulting an ambiguous call.



This may be related to bug 49505 of GCC.





Second, even though the second function template does not exist, the call should still be ill-formed. According to [temp.arg.explicit]/3:




... A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments ...




Only trailing template parameter pack can be deduced to an empty pack, while the first unnamed template parameter pack class... is not a trailing template parameter pack.



Both GCC (bug 69623) and Clang (bug 26435) have bugs for this issue.






share|improve this answer















There are two issues here.





First, [temp.deduct.partial]/12 (I also quote the example since it is similar to yours) says:




In most cases, deduction fails if not all template parameters have values, but for partial ordering purposes a template parameter may remain without a value provided it is not used in the types being used for partial ordering. [ Note: A template parameter used in a non-deduced context is considered used. — end note ] [ Example:



template <class T> T f(int);            // #1
template <class T, class U> T f(U); // #2
void g() {
f<int>(1); // calls #1
}


— end example ]




The types being used for partial ordering are T... according to [temp.deduct.partial]/3:




The types used to determine the ordering depend on the context in which the partial ordering is done:




  • In the context of a function call, the types used are those function parameter types for which the function call has arguments.


  • ...





So the first unnamed template parameter pack class... does not affect the result of partial ordering. Since there are no other differences for the two function templates, neither is more specialized than the other, resulting an ambiguous call.



This may be related to bug 49505 of GCC.





Second, even though the second function template does not exist, the call should still be ill-formed. According to [temp.arg.explicit]/3:




... A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments ...




Only trailing template parameter pack can be deduced to an empty pack, while the first unnamed template parameter pack class... is not a trailing template parameter pack.



Both GCC (bug 69623) and Clang (bug 26435) have bugs for this issue.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 19 '18 at 8:41

























answered Nov 18 '18 at 16:28









xskxzrxskxzr

6,37682252




6,37682252








  • 1





    See also stackoverflow.com/a/41069348/1639256

    – Oktalist
    Nov 18 '18 at 16:53











  • @Oktalist That's a different issue. That issue is fixed by an editorial change.

    – xskxzr
    Nov 18 '18 at 17:20














  • 1





    See also stackoverflow.com/a/41069348/1639256

    – Oktalist
    Nov 18 '18 at 16:53











  • @Oktalist That's a different issue. That issue is fixed by an editorial change.

    – xskxzr
    Nov 18 '18 at 17:20








1




1





See also stackoverflow.com/a/41069348/1639256

– Oktalist
Nov 18 '18 at 16:53





See also stackoverflow.com/a/41069348/1639256

– Oktalist
Nov 18 '18 at 16:53













@Oktalist That's a different issue. That issue is fixed by an editorial change.

– xskxzr
Nov 18 '18 at 17:20





@Oktalist That's a different issue. That issue is fixed by an editorial change.

– xskxzr
Nov 18 '18 at 17:20


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53358165%2ffunction-template-overload-resolution-with-two-parameter-packs%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Tangent Lines Diagram Along Smooth Curve

Yusuf al-Mu'taman ibn Hud

Zucchini