admin管理员组文章数量:1024603
The current draft standard contains this (see the last sentence of this paragraph): "When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the type of that pack is never deduced."
Now, what does it mean that the pack is never deduced? If the user doesn't specify the value of the pack, and also it is not deduced, shouldn't it be a compile failure?
Current compilers handle this case defining the pack as empty.
This is a stripped down example from the draft:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x, y, z); // error: Types is not deduced
}
This doesn't compile. However, if I modify the example to only use 1 argument, the example compiles:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x); // compiles
}
Is there anything in the standard that specifies that in this case, the pack should be empty? Why isn't this a compile error?
I understand, that in the latter example, it is obvious that Types
is empty, as this is the only way to make the compilation succeed. But, in the previous example, it should also be obvious that the "x, y" part corresponds to Types
. I know, that Types
is not deduced, so the example shouldn't compile. But then what makes the second example compile?
Types
is not deduced either here, so if we consider the "error: Types is not deduced" comment (which made the example not compile), this should make the example ill-formed as well.
Shouldn't the cited quote at the beginning sound like: "When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the pack is deduced as empty." (which is of course looks a little bit weird, because it defines something which is got deduced in a non-deduced context, but isn't this what's happening here?)
Note: there was a similar question before. But I think my question is more explicit, and contains a quote from the current draft (which quote wasn't present back then), so I think it's better to have a new question.
Reflecting to the comment "It is not deduced as empty, it is non deduced and use the one provided by the call (which is empty)"
At first, this seemed to be the answer. However, see this example:
#include <type_traits>
template <typename A, typename ...B, typename C>
void foo(A, B..., C) {
static_assert(std::is_same_v<A, int>);
static_assert(sizeof...(B)==0);
static_assert(std::is_same_v<C, const char *>);
}
int main() {
foo<int>(42, "");
}
Here, I'd argue whether the call foo
provides the value of B
or not. If the call had A
specified, like foo<int>(42, "")
, then I could say this specifies B
as empty, because <int>
can be considered as <int, empty>
. But in the example there are no template arguments specified for foo
at all. Sure, the empty template argument list contains the empty set for B
. But this way of thinking is a little bit unexpected.
The current draft standard contains this (see the last sentence of this paragraph): "When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the type of that pack is never deduced."
Now, what does it mean that the pack is never deduced? If the user doesn't specify the value of the pack, and also it is not deduced, shouldn't it be a compile failure?
Current compilers handle this case defining the pack as empty.
This is a stripped down example from the draft:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x, y, z); // error: Types is not deduced
}
This doesn't compile. However, if I modify the example to only use 1 argument, the example compiles:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x); // compiles
}
Is there anything in the standard that specifies that in this case, the pack should be empty? Why isn't this a compile error?
I understand, that in the latter example, it is obvious that Types
is empty, as this is the only way to make the compilation succeed. But, in the previous example, it should also be obvious that the "x, y" part corresponds to Types
. I know, that Types
is not deduced, so the example shouldn't compile. But then what makes the second example compile?
Types
is not deduced either here, so if we consider the "error: Types is not deduced" comment (which made the example not compile), this should make the example ill-formed as well.
Shouldn't the cited quote at the beginning sound like: "When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the pack is deduced as empty." (which is of course looks a little bit weird, because it defines something which is got deduced in a non-deduced context, but isn't this what's happening here?)
Note: there was a similar question before. But I think my question is more explicit, and contains a quote from the current draft (which quote wasn't present back then), so I think it's better to have a new question.
Reflecting to the comment "It is not deduced as empty, it is non deduced and use the one provided by the call (which is empty)"
At first, this seemed to be the answer. However, see this example:
#include <type_traits>
template <typename A, typename ...B, typename C>
void foo(A, B..., C) {
static_assert(std::is_same_v<A, int>);
static_assert(sizeof...(B)==0);
static_assert(std::is_same_v<C, const char *>);
}
int main() {
foo<int>(42, "");
}
Here, I'd argue whether the call foo
provides the value of B
or not. If the call had A
specified, like foo<int>(42, "")
, then I could say this specifies B
as empty, because <int>
can be considered as <int, empty>
. But in the example there are no template arguments specified for foo
at all. Sure, the empty template argument list contains the empty set for B
. But this way of thinking is a little bit unexpected.
1 Answer
Reset to default -5When a function parameter pack is in a non-deduced context, it means that the compiler cannot determine the types for that pack based on the arguments provided. In this situation, if the pack is not deduced, it does not cause a compilation error; instead, it is treated as an empty pack.
In your first example with g1(x, y, z)
, the compiler cannot deduce the types for Types
because it is in a non-deduced context (due to the presence of T1
after the pack). This results in a compilation error since it requires at least one type to be deduced for Types
.
In the second example with g1(x)
, there are no arguments for Types
, so it is clear that Types
must be empty. The compiler allows this because it can logically conclude that there are no types to deduce.
The standard does not explicitly state that the pack should be empty in this context, but it is implied that if no types can be deduced, the pack is treated as empty, which allows the code to compile without error. So, while it might seem confusing, the rules of the language allow for this behavior, and it is consistent with how the compiler handles these situations.
The current draft standard contains this (see the last sentence of this paragraph): "When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the type of that pack is never deduced."
Now, what does it mean that the pack is never deduced? If the user doesn't specify the value of the pack, and also it is not deduced, shouldn't it be a compile failure?
Current compilers handle this case defining the pack as empty.
This is a stripped down example from the draft:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x, y, z); // error: Types is not deduced
}
This doesn't compile. However, if I modify the example to only use 1 argument, the example compiles:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x); // compiles
}
Is there anything in the standard that specifies that in this case, the pack should be empty? Why isn't this a compile error?
I understand, that in the latter example, it is obvious that Types
is empty, as this is the only way to make the compilation succeed. But, in the previous example, it should also be obvious that the "x, y" part corresponds to Types
. I know, that Types
is not deduced, so the example shouldn't compile. But then what makes the second example compile?
Types
is not deduced either here, so if we consider the "error: Types is not deduced" comment (which made the example not compile), this should make the example ill-formed as well.
Shouldn't the cited quote at the beginning sound like: "When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the pack is deduced as empty." (which is of course looks a little bit weird, because it defines something which is got deduced in a non-deduced context, but isn't this what's happening here?)
Note: there was a similar question before. But I think my question is more explicit, and contains a quote from the current draft (which quote wasn't present back then), so I think it's better to have a new question.
Reflecting to the comment "It is not deduced as empty, it is non deduced and use the one provided by the call (which is empty)"
At first, this seemed to be the answer. However, see this example:
#include <type_traits>
template <typename A, typename ...B, typename C>
void foo(A, B..., C) {
static_assert(std::is_same_v<A, int>);
static_assert(sizeof...(B)==0);
static_assert(std::is_same_v<C, const char *>);
}
int main() {
foo<int>(42, "");
}
Here, I'd argue whether the call foo
provides the value of B
or not. If the call had A
specified, like foo<int>(42, "")
, then I could say this specifies B
as empty, because <int>
can be considered as <int, empty>
. But in the example there are no template arguments specified for foo
at all. Sure, the empty template argument list contains the empty set for B
. But this way of thinking is a little bit unexpected.
The current draft standard contains this (see the last sentence of this paragraph): "When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the type of that pack is never deduced."
Now, what does it mean that the pack is never deduced? If the user doesn't specify the value of the pack, and also it is not deduced, shouldn't it be a compile failure?
Current compilers handle this case defining the pack as empty.
This is a stripped down example from the draft:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x, y, z); // error: Types is not deduced
}
This doesn't compile. However, if I modify the example to only use 1 argument, the example compiles:
template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {
const int z = x;
g1(x); // compiles
}
Is there anything in the standard that specifies that in this case, the pack should be empty? Why isn't this a compile error?
I understand, that in the latter example, it is obvious that Types
is empty, as this is the only way to make the compilation succeed. But, in the previous example, it should also be obvious that the "x, y" part corresponds to Types
. I know, that Types
is not deduced, so the example shouldn't compile. But then what makes the second example compile?
Types
is not deduced either here, so if we consider the "error: Types is not deduced" comment (which made the example not compile), this should make the example ill-formed as well.
Shouldn't the cited quote at the beginning sound like: "When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the pack is deduced as empty." (which is of course looks a little bit weird, because it defines something which is got deduced in a non-deduced context, but isn't this what's happening here?)
Note: there was a similar question before. But I think my question is more explicit, and contains a quote from the current draft (which quote wasn't present back then), so I think it's better to have a new question.
Reflecting to the comment "It is not deduced as empty, it is non deduced and use the one provided by the call (which is empty)"
At first, this seemed to be the answer. However, see this example:
#include <type_traits>
template <typename A, typename ...B, typename C>
void foo(A, B..., C) {
static_assert(std::is_same_v<A, int>);
static_assert(sizeof...(B)==0);
static_assert(std::is_same_v<C, const char *>);
}
int main() {
foo<int>(42, "");
}
Here, I'd argue whether the call foo
provides the value of B
or not. If the call had A
specified, like foo<int>(42, "")
, then I could say this specifies B
as empty, because <int>
can be considered as <int, empty>
. But in the example there are no template arguments specified for foo
at all. Sure, the empty template argument list contains the empty set for B
. But this way of thinking is a little bit unexpected.
- 5 It is not deduced as empty, it is non deduced and use the one provided by the call (which is empty) – Jarod42 Commented Nov 18, 2024 at 14:24
- @Jarod42: thanks, it sounds like a correct explanation. And I suppose, if there is a second non-trailing pack, it will be always empty, as the first parameter pack always consumes all the specified template arguments (I wonder, is this behavior specified?). godbolt./z/zdMGr54he – geza Commented Nov 18, 2024 at 14:43
-
I suppose the distinction is necessary because
g1<int,int>(42,x);
is fine. HereTypes
is non-deduced (but not empty) godbolt./z/5sPT78j3n – 463035818_is_not_an_ai Commented Nov 18, 2024 at 14:44
1 Answer
Reset to default -5When a function parameter pack is in a non-deduced context, it means that the compiler cannot determine the types for that pack based on the arguments provided. In this situation, if the pack is not deduced, it does not cause a compilation error; instead, it is treated as an empty pack.
In your first example with g1(x, y, z)
, the compiler cannot deduce the types for Types
because it is in a non-deduced context (due to the presence of T1
after the pack). This results in a compilation error since it requires at least one type to be deduced for Types
.
In the second example with g1(x)
, there are no arguments for Types
, so it is clear that Types
must be empty. The compiler allows this because it can logically conclude that there are no types to deduce.
The standard does not explicitly state that the pack should be empty in this context, but it is implied that if no types can be deduced, the pack is treated as empty, which allows the code to compile without error. So, while it might seem confusing, the rules of the language allow for this behavior, and it is consistent with how the compiler handles these situations.
本文标签:
版权声明:本文标题:c++ - What happens with the deduction of a function parameter pack, if it appears in a non-deduced context? - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745613021a2159117.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
g1<int,int>(42,x);
is fine. HereTypes
is non-deduced (but not empty) godbolt./z/5sPT78j3n – 463035818_is_not_an_ai Commented Nov 18, 2024 at 14:44