使用其他模板类型参数作为要在函数签名中使用的类型别名声明
Using additional template type parameters as type alias declarations to use in function's signature
给定一个函数模板,其签名在多个位置包含冗长的名称,例如,一个函数模板采用两个包含自身大小 3std::array
s 的std::array
,并且还返回一个,
// Clumsy - requires multiple line breaks
template <typename T, std::size_t n>
typename std::array<std::array<T, 3>, n>
foo(const typename std::array<std::array<T, 3>, n>& points_a,
const typename std::array<std::array<T, 3>, n>& points_b)
{
typename std::array<std::array<T, 3>, n> result;
// .. process ..
return result;
}
引入具有派生默认值的其他冗余模板类型参数以使函数的签名更清晰,这是否是不明智的?在示例的情况下,typename Points = typename std::array<std::array<T, 3>, n>
将添加到模板参数中:
// Better
template <typename T, std::size_t n, typename Points = typename std::array<std::array<T, 3>, n>>
Points bar(const Points& points, const Points& offsets)
{
Points result;
// .. process ..
return result;
}
为了防止滥用其他模板类型参数(显然客户端根本不会使用它(,该函数可能会应用编译时检查来验证其实例化是否导致使用参数的默认类型(通过if constexpr (std::is_same<...>())
(。
这个问题的重点是减少函数模板签名中的代码重复(当重复确实降低了可读性时(。这种方法对我来说似乎很自然,但我不确定是否会出现我无法看到的任何问题。
谢谢。
我没有看到您的附加类型解决方案有问题(除了您刚刚看到的所解释类型的风险(。
但我提出了一个完全不同的解决方案:使foo()
接收一个通用类型名AA
(用于数组数组(
template <typename AA>
AA foo (AA const & points_a, AA const & points_b)
而且,如果需要它们,您可以在函数内部提取内部类型(旧T
(,using
using T = typename AA::value_type::value_type;
并且,使用数组的std::tuple_size
专用化,以及外部维度(旧n
(
static constexpr auto n { std::tuple_size<AA>::value };
如果还想强制要求内部std::array
的大小为 3,可以通过 SFINAE(使用返回类型的std::enable_if_t
(或通过函数内部的static_assert()
static_assert( std::tuple_size<typename AA::value_type>::value == 3u );
以下是完整的工作示例
#include <array>
#include <utility>
#include <iostream>
template <typename AA>
AA foo (AA const & points_a, AA const & points_b)
{
using T = typename AA::value_type::value_type;
static constexpr auto n { std::tuple_size<AA>::value };
static_assert( std::tuple_size<typename AA::value_type>::value == 3u );
std::cout << std::is_same<T, int>::value << ' ' << n << std::endl;
AA result;
// .. process ..
return result;
}
int main ()
{
std::array<std::array<int, 3u>, 5u> a;
std::array<std::array<long, 3u>, 7u> b;
std::array<std::array<long, 5u>, 9u> c;
foo(a, a); // print 1 5
foo(b, b); // print 0 7
// foo(c, c); // compilation error
}
相关文章:
- 将类型声明为类型模板参数的模板参数的一部分是否合法?
- 当返回类型声明为 ListNode 时,我们是否可以返回 false<T>*
- 如何使用自定义类型声明Arduino数组?
- 将函数参数类型声明为 auto
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- 在没有标识符的情况下如何读取复杂的C++类型声明?
- 模板函数参数显式类型声明
- 使用指针遍历一系列基元类型声明?
- 字符类型声明和验证
- 使用本地类型声明的G lambda被使用但从未定义 - 确实是一个错误
- 为什么 c++ lambda 捕获不需要类型声明?
- 为什么没有"int"类型声明时输出不同?
- C++如何使用虚拟基类型声明全局静态分配的变量
- 我可以使用预处理器将一个类型声明替换为另一个类型声明吗?
- 如何将数据类型声明从.cpp文件传输到 .cu 文件
- C++17 枚举类型声明
- 条件类型声明
- 具有特定参数的特定构造函数的类型声明
- 我可以使用相同的名称为周围作用域中的类型声明成员类型别名吗
- 函数调用之前,C 类型声明