[英]Using std::is_same with structural (non-type) template parameters
考虑一个包含任何类型的结构模板参数的模板类型。 出于示例的目的,定义了value_type<auto V>
。
我们还声明了一个constexpr structure
,其中包含一些具有自定义构造函数的成员整数类型,这些构造函数使用非平凡的表达式设置成员值(需要的不仅仅是内存副本)。
尝试将结构输入value_type
并使用std::is_same
将其与另一个实例进行比较。
说明案例的示例代码:
#include <iostream>
#include <type_traits>
template <auto V>
struct value_type
{
using type = decltype(V);
static constexpr type value = V;
};
struct hmm
{
//Both constructors set b=4 by default
constexpr hmm(int x, int y = 8) : a(x), b(y / 2) { }
constexpr hmm(float c, int z = 2) : a((int)c), b(z * 2) { }
const int a;
const int b;
friend constexpr bool operator==(const hmm& a, const hmm& b) { return false; }
friend constexpr bool operator!=(const hmm& a, const hmm& b) { return true; }
};
int main()
{
std::cout << (std::is_same_v<value_type<hmm(2)>, value_type<hmm(3.5f)>>) << ", ";
std::cout << (std::is_same_v<value_type<hmm(5)>, value_type<hmm(5.11112f)>>) << ", ";
std::cout << (std::is_same_v<value_type<hmm(5, 7)>, value_type<hmm(5.11112f)>>) << ", ";
std::cout << (std::is_same_v<value_type<hmm(5, 12)>, value_type<hmm(5.11112f, 3)>>) << std::endl;
return 0;
}
此代码在 gcc 0, 1, 0, 1
msvc 和 clang 上打印 0、1、0、1。 这是完全有道理的,但是,它让我想知道这种机制的局限性是什么。
从外观上看,他们的成员在构造后被检查,但显然没有使用比较运算符。
而且,更一般地说,根据使用<T,T>
专业化( source )的潜在is_same
实现:
template<class T, class U>
struct is_same : std::false_type {};
template<class T>
struct is_same<T, T> : std::true_type {};
<T,T>
特化的上下文中,匹配类型T, U
被视为同一实体的规则是什么?
- 这些类型的比较究竟是如何进行的?
- 这种行为是跨编译器标准化的,还是只是运气好,它们似乎都遵循相同的模式?
根据cppref 上的 NTTP ,强调我的:
命名类类型 T 的非类型模板形参的标识符表示类型为 const T 的静态存储持续时间对象,称为模板形参对象,其值是对应模板实参转换为模板参数。 相同类型的程序中所有具有相同值的模板参数表示相同的模板参数对象。 模板参数对象应具有不断的破坏。
和类型等价:
模板参数等价用于确定两个模板 ID 是否相同。
两个值是模板参数等效的,如果它们是相同的类型并且
- 它们是整数或枚举类型,并且它们的值相同
- 或者它们是指针类型并且它们具有相同的指针值
- 或者它们是指向成员的指针类型并且它们引用同一个类成员或者都是空成员指针值
- 或者它们是左值引用类型并且它们引用相同的对象 -> - 或函数
- 或者它们是 std::nullptr_t 类型
- 或者它们是浮点类型并且它们的值相同
- 或者它们是数组类型(在这种情况下,数组必须是某个类/联合的成员对象)并且它们对应的元素是模板参数等效的
- 或者它们是联合类型,并且它们都没有活动成员,或者它们具有相同的活动成员并且它们的活动成员是模板参数等效的
- 或者它们是浮点类型并且它们的值相同
- 或者它们是非联合类类型,并且它们对应的直接子对象和引用成员是模板参数等效的
没有比较,但只涉及类型等价。 如果它们具有相同的值,则它们都引用同一个对象。 而已。
在您的情况下, hmm(5)
和hmm(5.11112f)
指的是同一个对象,但不在hmm(2)
和hmm(3)
之间。
- 是否有符合标准的方法来覆盖这种比较?
我相信现在是不允许的。
- 在 <T,T> 特化的上下文中,匹配类型 T、U 被视为同一实体的规则是什么?
它们与 cv-qualifiers 具有完全相同的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.