参数包必须位于参数列表的末尾...何时以及为什么?

2023-03-11C/C++开发问题
5

本文介绍了参数包必须位于参数列表的末尾...何时以及为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

如果参数列表绑定到一个类,我不明白为什么参数包必须位于参数列表的末尾,而如果参数列表是成员方法声明的一部分,则约束会放宽.

换句话说,这个编译:

class C {template无效 fn() { }};

以下没有:

templateC类{};

为什么第一种情况被认为是正确的,而第二种情况则不是?
我的意思是,如果是合法的语法,不应该在这两种情况下都如此吗?

说清楚,真正的问题是我定义了一个类似于以下的类:

templateC类{};

将分配器类型作为最后一种类型会很受欢迎,但我可以以某种方式解决它(无论如何,如果你有一个建议,它会受到赞赏,也许你的建议比我的更优雅!!).
也就是说,我收到了错误:

<块引用>

参数包'Args'必须在模板参数列表的末尾

所以,我只是想完全理解为什么它在某些情况下被接受,而在另一些情况下却不是.

这里 是一个类似的问题,但它只是解释了如何解决问题,这对我来说很清楚.

解决方案

它对函数模板有效,但仅当参数推导可以帮助编译器解析模板参数时,就目前而言,您的函数模板示例几乎没有用,因为

>

template无效 fn() { }int main() { fn();}

test.cpp:在函数int main()"中:test.cpp:2:32: 错误:没有匹配的函数来调用fn()"int main() { fn();}^test.cpp:1:57:注意:候选:模板无效 fn()template无效 fn() { }^test.cpp:1:57: 注意:模板参数推导/替换失败:test.cpp:2:32: 注意:无法推导出模板参数S"int main() { fn();}

编译器无法确定哪些模板参数属于参数包,哪些属于S.事实上作为@T.C.指出它实际上应该是一个语法错误,因为以这种方式定义的函数模板永远无法实例化.

更有用的函数模板应该是这样的

templatevoid fn(S s) { }

因为现在编译器能够明确地将函数参数 s 与模板类型 S 匹配,副作用是 S总是被推导出 - 第一个之后的所有显式模板参数都属于Args.

这些都不适用于(主要)类模板,不会推导出参数,并且明确禁止:

来自 n4567 草案

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf

[temp.param]/11

<块引用>

[...]如果主类模板或别名的模板参数模板是模板参数包,它应该是最后一个模板参数.[...]

(如果它们被推导出来,就会像函数模板示例中那样含糊不清).

I don't get the reason for which a parameter pack must be at the end of the parameter list if the latter is bound to a class, while the constraint is relaxed if the parameter list is part of a member method declaration.

In other terms, this one compiles:

class C {
    template<typename T, typename... Args, typename S>
    void fn() { }
};

The following one does not:

template<typename T, typename... Args, typename S>
class C { };

Why is the first case considered right and the second one is not?
I mean, if it's legal syntax, shouldn't it be in both the cases?

To be clear, the real problem is that I was defining a class similar to the following one:

template<typename T, typename... Args, typename Allocator>
class C { };

Having the allocator type as the last type would be appreciated, but I can work around it somehow (anyway, if you have a suggestion it's appreciated, maybe yours are far more elegant than mine!!).
That said, I got the error:

parameter pack 'Args' must be at the end of the template parameter list

So, I was just curious to fully understand why it's accepted in some cases, but it is not in some others.

Here is a similar question, but it simply explains how to solve the problem and that was quite clear to me.

解决方案

It is valid for function templates but only when argument deduction can help the compiler resolve the template parameters, as it stands your function template example is virtually useless because

template<typename T, typename... Args, typename S> void fn() { }
int main() { fn<int, int, int>(); }

test.cpp: In function 'int main()':
test.cpp:2:32: error: no matching function for call to 'fn()'
 int main() { fn<int, int, int>(); }
                                ^
test.cpp:1:57: note: candidate: template<class T, class ... Args, class S> void fn()
 template<typename T, typename... Args, typename S> void fn() { }
                                                         ^
test.cpp:1:57: note:   template argument deduction/substitution failed:
test.cpp:2:32: note:   couldn't deduce template parameter 'S'
 int main() { fn<int, int, int>(); }

the compiler has no way of determining which template parameters belong to the parameter pack, and which to S. In fact as @T.C. points out it should actually be a syntax error because a function template defined in this manner cannot ever be instantiated.

A more useful function template would be something like

template<typename T, typename... Args, typename S> void fn(S s) { }

as now the compiler is able to unambiguously match the function parameter s with the template type S, with the side effect that S will always be deduced - all explicit template parameters after the first will belong to Args.

None of this works for (primary) class templates, parameters aren't deduced and it's expressly forbidden:

From draft n4567

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf

[temp.param] / 11

[...]If a template-parameter of a primary class template or alias template is a template parameter pack, it shall be the last template-parameter.[...]

(if they were deduced it would be ambiguous as in the function template example).

这篇关于参数包必须位于参数列表的末尾...何时以及为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

The End

相关推荐

无法访问 C++ std::set 中对象的非常量成员函数

无法访问 C++ std::set 中对象的非常量成员函数

Unable to access non-const member functions of objects in C++ std::set(无法访问 C++ std::set 中对象的非常量成员函数)...
2024-08-14 C/C++开发问题
17

从 lambda 构造 std::function 参数

从 lambda 构造 std::function 参数

Constructing std::function argument from lambda(从 lambda 构造 std::function 参数)...
2024-08-14 C/C++开发问题
25

STL BigInt 类实现

STL BigInt 类实现

STL BigInt class implementation(STL BigInt 类实现)...
2024-08-14 C/C++开发问题
3

使用 std::atomic 和 std::condition_variable 同步不可靠

使用 std::atomic 和 std::condition_variable 同步不可靠

Sync is unreliable using std::atomic and std::condition_variable(使用 std::atomic 和 std::condition_variable 同步不可靠)...
2024-08-14 C/C++开发问题
17

在 STL 中将列表元素移动到末尾

在 STL 中将列表元素移动到末尾

Move list element to the end in STL(在 STL 中将列表元素移动到末尾)...
2024-08-14 C/C++开发问题
9

为什么禁止对存储在 STL 容器中的类重载 operator&amp;()?

为什么禁止对存储在 STL 容器中的类重载 operator&amp;()?

Why is overloading operatoramp;() prohibited for classes stored in STL containers?(为什么禁止对存储在 STL 容器中的类重载 operatoramp;()?)...
2024-08-14 C/C++开发问题
6

热门文章

1LNK2038:检测到“RuntimeLibrary"不匹配:值“MT_StaticRelease" 2c++ 编译错误:ISO C++ 禁止指针和整数之间的比较 3CMake 找不到源文件 (add_executable) 4Cmake 链接库目标链接错误 5如何使用 VideoWriter 从 OpenCV 打开 GStreamer 管道 6CMakeLists.txt:30 (project) 中的 CMake 错误:找不到 CMAKE_C_COMPILER 7CMake 无法确定目标的链接器语言 8如何解决munmap_chunk():C++中的无效指针错误

热门精品源码

最新VIP资源

1多功能实用站长工具箱html功能模板 2多风格简历在线生成程序网页模板 3论文相似度查询系统源码 4响应式旅游景点宣传推广页面模板 5在线起名宣传推广网站源码 6酷黑微信小程序网站开发宣传页模板 7房产销售交易中介网站模板 8小学作业自动生成程序