【问题标题】:std::is_same - Use-case of inherited functions from integral_constantstd::is_same - 从integral_constant 继承函数的用例
【发布时间】:2019-05-26 20:33:37
【问题描述】:

查看std::is_same的实现我们可以看到一些内部函数(继承自integral_constant)。为了方便,我复制一下g++代码:

  template<typename _Tp, _Tp __v>
  struct integral_constant {
      static constexpr _Tp                value = __v;
      typedef _Tp                         value_type;
      typedef integral_constant<_Tp, __v> type;
      constexpr operator value_type()   const noexcept { return value; }
      constexpr value_type operator()() const noexcept { return value; }
  };

  template<typename, typename>
  struct is_same : public integral_constant<bool, false> { };

  template<typename _Tp>
  struct is_same<_Tp, _Tp> : public integral_constant<bool, true> { };

这为我们提供了几个如何使用它的选项:

  bool a1 = is_same<int, int>{};               // instantiate & then cast implicitly
  bool a2 = is_same<int, int>();               // instantiate & then cast implicitly
  bool a3 = is_same<int, int>::value;          // use static member
  bool a4 = is_same<int, int>{}();             // instantiate & then use operator() 
  bool a5 = is_same<int, int>{}.operator()();  // instantiate & then use operator()

我想知道这些额外功能有哪些用例,以及为什么会使用例如像

这样的简短实现
  template<class, class> constexpr bool is_same = false;
  template<class T> constexpr bool is_same<T,T> = true;

还不够?那么我们可以只写bool a = is_same&lt;int,int&gt;而不写{}()::value

任何想法表示赞赏。

【问题讨论】:

  • is_same 比变量模板早了大约十年。在 C++11 中,这是最直接、最方便的实现。如果它现在被发明出来,它的设计可能会有所不同。
  • 你描述的是std::is_same_v

标签: c++ templates c++17 constexpr


【解决方案1】:

这个问题的答案在很大程度上是历史性的。类型特征早于变量模板十年,因此您提出的选项是不合时宜的。出于可用性原因,其余部分是零碎添加的。


std::integral_constant 早在 2003 年就通过N1424 引入。所以这是非常古老的技术,C++03 技术。当时的样子是这样的:

template <class T, T v> 
struct integral_constant
{
   static  const T                value = v;
   typedef T                      value_type;
   typedef integral_constant<T,v> type;
};

您没有看到任何其他成员函数,请注意value 也只是static const,而不是static constexpr。毕竟还没有constexpr

多年后,在 C++0x 的开发过程中,出现了一个库问题 (LWG1019),鉴于新添加的 constexpr,将其扩展到:

template <class T, T v>
struct integral_constant {
  static constexpr T value = v;
  typedef T value_type;
  typedef integral_constant<T,v> type;
  constexpr operator value_type() { return value; }
};

N2976 已解决此问题。

转换函数的动机是它允许您使用integral_constant 类型的对象作为这些值。对于某些风格的元编程,如果你有一个函数可以直接返回,比如,true_type,你可以直接使用它:

std::true_type foo();    
if (foo()) { ... }

而不必写if (foo().value) 或其他类似的奇怪的东西。但是,对于非布尔常量,given 对象获取值的唯一方法是访问 value 成员或进行显式转换(后者需要您知道类型):

constant.value
static_cast<???>(constant)

这导致 N3545 在 2013 年添加了调用运算符,允许您编写 constant() 以将值拉回。最后一个添加真的有用吗?我不知道。

值得注意的是,所有这些早于变量模板 - 其第一个修订版是N3615。您建议将 is_same 用作变量 bool 模板的选项直到后来才成为选项。即使使用可变模板,拥有不同的类型也很方便,所以即使可能,我也不确定我们是否会走这条路。回想起来很难说。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多