c++ - 使用额外的模板类型参数作为类型别名声明以在函数的签名中使用

标签 c++ templates c++17 stdarray

给定一个函数模板,其签名在多个位置包含一个冗长的名称,例如一个函数模板,它包含两个 std::array s,其中包含 size-3 std::array s 并返回一个,

// 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<...>()) ) .

这个问题的重点是减少函数模板签名中的代码重复(当重复确实降低易读性时)。这种方法对我来说很自然,但我不确定是否会出现我看不到的问题。

谢谢。

最佳答案

我没有看到您的 additional-typename 解决方案存在问题(除了风险,您刚刚看到的类型已说明)。

但我提出了一个完全不同的解决方案:让 foo() 接收一个通用类型名 AA (对于 Array-Array)

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 返回type) 或通过函数内的 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

 }

关于c++ - 使用额外的模板类型参数作为类型别名声明以在函数的签名中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51873660/

相关文章:

c++ - “对象”尚未声明错误

c++ - 如何让编译器忽略这个计算结果为 false 的 if-constexpr?

c++ - 如何在模板参数中分离函数类型返回类型和参数

c++ - 与更具可读性的方法相比,C++ 中按位异或的效率

c++ - 字符串。 TCHAR LPWCS LPCTSTR CString。这是什么,简单快速

c++ - 编译器如何优化模板?

java - 如何在velocity模板中使用java方法获取列表

c++ - 为什么 C++ 标准规定模板中的非限定名称是非依赖的?

macos - 错误 : 'uncaught_exceptions' is unavailable: introduced in macOS 10. 12

C++ 输入流