Function template overload resolution with two parameter packs











up vote
8
down vote

favorite
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




















  • 1




    first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?
    – Richard Hodges
    Nov 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 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.
    – eukaryota
    Nov 18 at 9:49















up vote
8
down vote

favorite
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




















  • 1




    first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?
    – Richard Hodges
    Nov 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 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.
    – eukaryota
    Nov 18 at 9:49













up vote
8
down vote

favorite
3









up vote
8
down vote

favorite
3






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 at 10:50

























asked Nov 18 at 5:27









eukaryota

94615




94615








  • 1




    first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?
    – Richard Hodges
    Nov 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 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.
    – eukaryota
    Nov 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 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 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.
    – eukaryota
    Nov 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 at 8:28




first f looks ill-formed to me. How could a compiler deterministically deduce the two packs?
– Richard Hodges
Nov 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 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 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.
– eukaryota
Nov 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.
– eukaryota
Nov 18 at 9:49












1 Answer
1






active

oldest

votes

















up vote
5
down vote



accepted










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 at 16:53










  • @Oktalist That's a different issue. That issue is fixed by an editorial change.
    – xskxzr
    Nov 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',
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








up vote
5
down vote



accepted










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 at 16:53










  • @Oktalist That's a different issue. That issue is fixed by an editorial change.
    – xskxzr
    Nov 18 at 17:20















up vote
5
down vote



accepted










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 at 16:53










  • @Oktalist That's a different issue. That issue is fixed by an editorial change.
    – xskxzr
    Nov 18 at 17:20













up vote
5
down vote



accepted







up vote
5
down vote



accepted






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 at 8:41

























answered Nov 18 at 16:28









xskxzr

5,75582051




5,75582051








  • 1




    See also stackoverflow.com/a/41069348/1639256
    – Oktalist
    Nov 18 at 16:53










  • @Oktalist That's a different issue. That issue is fixed by an editorial change.
    – xskxzr
    Nov 18 at 17:20














  • 1




    See also stackoverflow.com/a/41069348/1639256
    – Oktalist
    Nov 18 at 16:53










  • @Oktalist That's a different issue. That issue is fixed by an editorial change.
    – xskxzr
    Nov 18 at 17:20








1




1




See also stackoverflow.com/a/41069348/1639256
– Oktalist
Nov 18 at 16:53




See also stackoverflow.com/a/41069348/1639256
– Oktalist
Nov 18 at 16:53












@Oktalist That's a different issue. That issue is fixed by an editorial change.
– xskxzr
Nov 18 at 17:20




@Oktalist That's a different issue. That issue is fixed by an editorial change.
– xskxzr
Nov 18 at 17:20


















 

draft saved


draft discarded



















































 


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







Popular posts from this blog

Ottavio Pratesi

Tricia Helfer

15 giugno