Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用简洁的方式指定我不关心我的函数参数的模板参数?_C++_Templates_C++20 - Fatal编程技术网

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();
}