为什么same_as概念两次检查类型相等性? [英] Why does same_as concept check type equality twice?

查看:109
本文介绍了为什么same_as概念两次检查类型相等性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

https://en.cppreference中查看same_as概念的可能实现。 com / w / cpp / concepts / same_as 我注意到正在发生奇怪的事情。

Looking at the possible implementation of the same_as concept at https://en.cppreference.com/w/cpp/concepts/same_as i noticed something strange is happening.

namespace detail {
    template< class T, class U >
    concept SameHelper = std::is_same_v<T, U>;
}

template< class T, class U >
concept same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;

第一个问题是为什么 SameHelper 概念被爱吗?
第二个原因是为什么 same_as 检查 T 是否与 U U T 相同吗?

The first question is why a SameHelper concept is nedded? The second is why same_as checks if T is the same as U and U the same as T? Isn't it redundant?

推荐答案

有趣的问题。我最近看了安德鲁·萨顿(Andrew Sutton)关于概念的演讲,在问答环节中,有人问了以下问题(以下链接中的时间戳):
CppCon 2018:Andrew Sutton 60岁的概念:您需要知道的一切,而您不需要的一切

Interesting question. I have recently watched Andrew Sutton's talk on Concepts, and in the Q&A session someone asked the following question (timestamp in the following link): CppCon 2018: Andrew Sutton "Concepts in 60: Everything you need to know and nothing you don't"

因此,问题归结为:如果我有一个表示A&&的概念。 B&& C,另一个说C& amp; amp; B&&答:是等价的吗? Andrew回答是,但指出编译器具有一些内部方法(对用户透明)将这些概念分解为原子逻辑命题(原子约束(如安德鲁所说的术语),并检查它们是否等效。

So the question boils down to: If I have a concept that says A && B && C, another says C && B && A, would those be equivalent? Andrew answered yes, but pointed out the fact the compiler has some internal methods (that is transparent to the user) to decompose the concepts into atomic logical propositions (atomic constraints as Andrew worded the term) and check whether they are equivalent.

现在看看cppreference对<$ c $的描述c> std :: same_as :

Now look at what cppreference says about std::same_as:


std :: same_as< T,U> ; 包含 std :: same_as< U,T> ,反之亦然。

这基本上是一种如果且仅当关系:它们相互暗示。 (逻辑等价)

It is basically an "if-and-only-if" relationship: they imply each other. (Logical Equivalence)

我的推测是,这里的原子约束是 std :: is_same_v< T,U> 。编译器对待 std :: is_same_v 的方式可能使他们认为 std :: is_same_v< T,U> std :: is_same_v< U,T> 作为两个不同的约束(它们是不同的实体!)。因此,如果仅使用其中之一来实现 std :: same_as

My conjecture is that here the atomic constraints are std::is_same_v<T, U>. The way compilers treat std::is_same_v might make them think std::is_same_v<T, U> and std::is_same_v<U, T> as two different constraints (they are different entities!). So if you implement std::same_as using only one of them:

template< class T, class U >
concept same_as = detail::SameHelper<T, U>;

然后 std :: same_as< T,U> std :: same_as< U,T> 会爆炸到不同的原子约束而变得不相等。

Then std::same_as<T, U> and std::same_as<U, T> would "explode" to different atomic constrains and become not equivalent.

那么,为什么编译器会关心它?

Well, why does the compiler care?

考虑此示例

#include <type_traits>
#include <iostream>
#include <concepts>

template< class T, class U >
concept SameHelper = std::is_same_v<T, U>;

template< class T, class U >
concept my_same_as = SameHelper<T, U>;

// template< class T, class U >
// concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;

template< class T, class U> requires my_same_as<U, T>
void foo(T a, U b) {
    std::cout << "Not integral" << std::endl;
}

template< class T, class U> requires (my_same_as<T, U> && std::integral<T>)
void foo(T a, U b) {
    std::cout << "Integral" << std::endl;
}

int main() {
    foo(1, 2);
    return 0;
}

理想情况下, my_same_as< T,U> && std :: integral< T> 包含 my_same_as< U,T> ;因此,编译器应该选择第二个模板特化,除非...否则:编译器发出错误错误:重载的'foo(int,int)'的调用不明确

Ideally, my_same_as<T, U> && std::integral<T> subsumes my_same_as<U, T>; therefore, the compiler should select the second template specialization, except ... it does not: the compiler emits an error error: call of overloaded 'foo(int, int)' is ambiguous.

其原因在于,由于 my_same_as< U,T> my_same_as< T,U> 不相互包含, my_same_as< T,U> && std :: integral< T> my_same_as< U,T> 变得无可比拟(在包含关系下的部分约束集上) 。

The reason behind this is that since my_same_as<U, T> and my_same_as<T, U> does not subsume each other, my_same_as<T, U> && std::integral<T> and my_same_as<U, T> become incomparable (on the partially ordered set of constraints under the relation of subsumption).

但是,如果您替换

template< class T, class U >
concept my_same_as = SameHelper<T, U>;

with

template< class T, class U >
concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;

代码会编译。

这篇关于为什么same_as概念两次检查类型相等性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆