C++ 用简洁的方式指定我不关心我的函数参数的模板参数?
考虑以下代码:C++ 用简洁的方式指定我不关心我的函数参数的模板参数?,c++,templates,c++20,C++,Templates,C++20,考虑以下代码: int64_t signed_vector_size(const std::vector v){ return (int64_t)v.size(); } 这不起作用,因为std::vector是一个模板。但我的函数适用于每个T 简单的解决方法就是直接去做 (一) 或者,选择3 template<class, template<class...> class> inline constexpr bool is_specialization = fa
int64_t signed_vector_size(const std::vector v){
return (int64_t)v.size();
}
这不起作用,因为std::vector是一个模板。但我的函数适用于每个T
简单的解决方法就是直接去做
(一)
或者,选择3
template<class, template<class...> class>
inline constexpr bool is_specialization = false;
template<template<class...> class T, class... Args>
inline constexpr bool is_specialization<T<Args...>, T> = true;
template<class T>
concept Vec = is_specialization<T, std::vector>;
int64_t signed_vector_size(const Vec auto& v){
return (int64_t)v.size();
}
模板
inline constexpr bool为_=false;
模板
inline constexpr bool是_=true;
模板
概念向量=是专业化;
int64符号向量大小(常量向量自动&v){
返回(int64_t)v.size();
}
我喜欢第二种解决方案,但它接受任何v
,而我只想将其限制为向量类型。第三个是最好的,当只看函数时,但是指定概念是一个相对大量的工作
C++20语法是否有更短的方法来指定我想要任何std::vector
作为参数,或者是1。我们能做的最短的解决方案
注意:这是一个愚蠢的简化示例,请不要评论我如何花费太多时间来节省键入10个字符,或者我如何牺牲可读性(这是我个人的偏好,我理解为什么有些人喜欢显式模板语法)。注意,在标准C++20中,无效,但是,您可以使用GCC作为扩展支持的以下语法完全实现您想要的
std::vector<auto>
std::vector模板只是某种东西的模式<代码>矢量
是模式<代码>矢量是一种类型。函数不能采用模式;它只能接受一种类型。因此,函数必须提供实际类型
因此,如果你想要一个函数,它接受模板的任何实例化,那么这个函数本身必须是一个模板,它本身必须需要模板作为参数所需要的一切。这必须在函数声明中明确说明
即使您的is\u专门化也有不足之处,因为它假定所有模板参数都是类型参数。它不适用于std::array
,因为它的一个参数是值,而不是类型
C++没有方便的机制来表达您想要表达的内容。你必须把它说清楚,或者接受一些不太理想的妥协
而且,从广义上讲,这可能不是一个好主意。如果您的函数已经必须是一个模板,那么使用任何大小的\u范围有什么害处?一旦您开始像这样扩展模板,您将发现自己不太可能被绑定到特定类型,而更愿意接受满足特定概念的任何类型
也就是说,很少有函数足够具体以至于需要vector
,但足够通用以至于对vector
的值类型也没有要求。这种语法如何
int64_t signed_vector_size(const instance_of<std::vector> auto& v){
return (int64_t)v.size();
}
int64符号向量大小(auto&v的常量实例大小){
返回(int64_t)v.size();
}
基本上,我们希望能够说“这个参数应该是某个模板的实例”。那么,你这么说
template<template<class...>class Z, class T>
struct is_instance_of : std::false_type {};
template<template<class...>class Z, class...Ts>
struct is_instance_of<Z, Z<Ts...>> : std::true_type {};
template<class T, template<class...>class Z>
concept instance_of = is_instance_of<Z, T>::value;
int64_t signed_vector_size(const instance_of<std::vector> auto& v){
return (int64_t)v.size();
}
模板
结构是:std::false_类型{}的_实例_;
模板
struct是:std::true_type{}的_实例_;
模板
concept-instance-of=is-instance-of::value;
int64符号向量大小(auto&v的常量实例大小){
返回(int64_t)v.size();
}
应该这样做。请注意,我没有使用Vec
别名;可以将部分参数传递给概念。您正在测试的类型是前置的
现在,我想说这有点反模式。我是说,那个尺寸?为什么它不能在非向量上工作?例如,std::span
s或std::deque
s
另外,
的instance_不支持std::array
,因为其中一个参数不是类型。在C++中,没有办法统一处理类型、模板和值参数。
对于类型、模板和值参数的每个模式,都需要不同的概念。这很尴尬。在我看来,您的第三个示例已经具备了执行此操作所需的最少代码量。您还可以将第一个版本更改为模板int64\t signed\u vector\u size(const std::vector&v)
以使其在所有情况下都能工作。我遗漏了一些东西,但是您的#1示例有什么问题吗?这似乎准确明确地说明了你的意思#3要复杂得多;现在读者必须去看看什么是Vec
,思考一下所有的模板机制。#3也有微妙的不同,因为它允许从std::vector
继承的任何东西工作。解决方案1似乎是meNice的明显选择,我认为它在C++20中没有实现,因为我只尝试了使用clang@尼古拉斯,这就是我删除它的原因。但显然我不能重新删除它,因为它已被接受。未被接受。。。我仍然会留下答案,因为我们可以在C++中得到答案23@NoSenseEtAl对。它还有一个价值,就是遇到它的人也会知道这种语法目前是无效的。我同意,答案是有用的。我还认为可以对它进行编辑,简单地声明这是一个GCC扩展支持的无效C++20,并删除关于它最初是一个错误答案的部分,但只有gcc实现了它。更新:答案被取消删除…@nosenseal我删除了它,因为我意识到它实际上不是有效的C++20。我不知道为什么它没有被删除。我想你应该不接受它,这样我可以再次删除它。
int64_t signed_vector_size(const instance_of<std::vector> auto& v){
return (int64_t)v.size();
}
template<template<class...>class Z, class T>
struct is_instance_of : std::false_type {};
template<template<class...>class Z, class...Ts>
struct is_instance_of<Z, Z<Ts...>> : std::true_type {};
template<class T, template<class...>class Z>
concept instance_of = is_instance_of<Z, T>::value;
int64_t signed_vector_size(const instance_of<std::vector> auto& v){
return (int64_t)v.size();
}