c++ - libstdc++对std::declval的实现问题

标签 c++ metaprogramming c++20 typetraits

不像 libc++MSVC-STL仅声明 std::declval 的函数签名, libstdc++std::declval 定义函数体,并使用 static_assert在内部确保它必须在未评估的上下文中使用:

template<typename _Tp, typename _Up = _Tp&&>
_Up 
__declval(int);

template<typename _Tp>
_Tp 
__declval(long);

template<typename _Tp>
auto 
declval() noexcept -> decltype(__declval<_Tp>(0));

template<typename _Tp>
struct __declval_protector {
  static const bool __stop = false;
};

template<typename _Tp>
auto 
declval() noexcept -> decltype(__declval<_Tp>(0)) {
  static_assert(__declval_protector<_Tp>::__stop,
    "declval() must not be used!");
  return __declval<_Tp>(0);
}
当我们尝试评估 std::declval 的返回值时, 这个 static_assert将被触发:
auto x = std::declval<int>(); // static assertion failed: declval() must not be used!
但是我发现在这个实现中,下面的代码也会被拒绝,因为static_assert失败( godbolt ):
#include <type_traits>

template<class T>
auto type() { return std::declval<T>(); }

using T = decltype(type<int>());
但似乎std::declval仍然在未评估的上下文中使用,因为我们尚未实际评估它。
上面的代码格式正确吗?如果是这样,它是一个库实现错误吗?标准是如何规定的?

最佳答案

该示例格式错误,因为 std::declval 的限制实际上是在表达式 where declval被命名,而不是根据抽象虚拟机是否会实际评估它的调用。std::declval上的要求是 [declval].2

Mandates: This function is not odr-used ([basic.def.odr]).


其中“授权”是指( [structure.specifications]/(3.2) )

Mandates: the conditions that, if not met, render the program ill-formed.


[basic.def.odr]/7 :

A function is odr-used if it is named by a potentially-evaluated expression or conversion.


而在 [basic.def.odr]/2 :

An expression or conversion is potentially evaluated unless it is an unevaluated operand ([expr.prop]), a subexpression thereof, or a conversion in an initialization or conversion sequence in such a context.


注意表达式 type<int>()最后一行是一个未计算的操作数。但是明显的表达std::declval<T>()type 的实例化定义中可能被评估。忽略这一点并不重要,它实际上不会被评估。
所以实际上 libc++ 和 MSVC-STL 实现是不正确的,因为除非另有说明,否则应该诊断格式错误的程序。

关于c++ - libstdc++对std::declval的实现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68590453/

相关文章:

c++ - 对重载函数 find_first_not_of 的模糊调用

c++ - 编译处理大量数字的时间斐波那契

c++ - 如何为带有接受模板参数的成员函数模板的类编写 C++ 概念?

c++ - 如何使用概念在 C++ 20 中提供默认实现?

c++ - C++中的 block 是什么?

c++ - std::lock_guard 构造函数实例化顺序

c++ - 无法打开包含文件 : 'vector.h' : No such file or directory

ruby 元 : Class. superclass.class == 类

c++ - 不允许非类型参数的部分模板特化

c++ - 错误 C2660 : 'std::allocator<char>::allocate' : function does not take 2 arguments