std::is_same - 从 integral_constant 继承函数的用例
std::is_same - Use-case of inherited functions from integral_constant
查看 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<int,int>
而不用 {}
或 ()
或 ::value
.
任何想法表示赞赏。
这个问题的答案在很大程度上是历史性的。类型特征早于变量模板十年,因此您提出的选项是不合时宜的。出于可用性原因,其余部分是零碎添加的。
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;
};
None 您看到的其他成员函数,请注意 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
类型的对象作为这些值。对于某些元编程风格,如果你有一个直接 returns 的函数,比如 true_type
,你可以直接使用它:
std::true_type foo();
if (foo()) { ... }
而不是必须写 if (foo().value)
或其他奇怪的东西。但是,对于 non-boolean 常量,给定 对象的值的唯一方法是访问 value
成员或进行显式转换(后者需要你知道类型):
constant.value
static_cast<???>(constant)
导致 N3545,在 2013 年,添加了调用运算符,允许您编写 constant()
将值拉回。最后这个加法真的有用吗?我不知道。
值得注意的是,所有这些 早于 变量模板 - 其第一次修订是 N3615。您建议让 is_same
只是一个变量 bool 模板的选项直到后来才成为一个选项。即使使用变量模板,拥有不同的类型也很方便,所以我不确定即使可能的话我们是否会走那条路。回想起来很难说。
查看 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<int,int>
而不用 {}
或 ()
或 ::value
.
任何想法表示赞赏。
这个问题的答案在很大程度上是历史性的。类型特征早于变量模板十年,因此您提出的选项是不合时宜的。出于可用性原因,其余部分是零碎添加的。
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; };
None 您看到的其他成员函数,请注意 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
类型的对象作为这些值。对于某些元编程风格,如果你有一个直接 returns 的函数,比如 true_type
,你可以直接使用它:
std::true_type foo();
if (foo()) { ... }
而不是必须写 if (foo().value)
或其他奇怪的东西。但是,对于 non-boolean 常量,给定 对象的值的唯一方法是访问 value
成员或进行显式转换(后者需要你知道类型):
constant.value
static_cast<???>(constant)
导致 N3545,在 2013 年,添加了调用运算符,允许您编写 constant()
将值拉回。最后这个加法真的有用吗?我不知道。
值得注意的是,所有这些 早于 变量模板 - 其第一次修订是 N3615。您建议让 is_same
只是一个变量 bool 模板的选项直到后来才成为一个选项。即使使用变量模板,拥有不同的类型也很方便,所以我不确定即使可能的话我们是否会走那条路。回想起来很难说。