Function template overload resolution with two parameter packs
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
add a comment |
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
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
add a comment |
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
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
c++ language-lawyer overload-resolution template-deduction
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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.
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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