gpt4 book ai didi

c++ - 为什么same_as概念两次检查类型相等性?

转载 作者:行者123 更新时间:2023-12-02 10:27:23 25 4
gpt4 key购买 nike

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

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相同?这不是多余的吗?

最佳答案

有趣的问题。我最近看了安德鲁·萨顿(Andrew Sutton)关于概念的演讲,在问答环节中,有人提出了以下问题(以下链接中的时间戳):
CppCon 2018: Andrew Sutton “Concepts in 60: Everything you need to know and nothing you don't”

因此问题可以归结为:If I have a concept that says A && B && C, another says C && B && A, would those be equivalent? Andrew回答"is",但指出了一个事实,编译器具有一些内部方法(对用户透明),可以将这些概念分解为原子逻辑命题(用Andrew的atomic constraints表示该术语),并检查是否它们是等效的。

现在看看cppreference关于std::same_as的内容:

std::same_as<T, U> subsumes std::same_as<U, T> and vice versa.



基本上,这是一种“如果且仅当”的关系:它们彼此暗示。 (逻辑等效)

我的猜测是,这里的原子约束是 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:

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

然后 std::same_as<T, U>std::same_as<U, T>将“爆炸”到不同的原子约束,并且变得不等效。

好吧,为什么编译器会关心?

考虑 this example:

#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>;因此,编译器应选择第二个模板特化,除非...否则:编译器将发出错误 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>变得无可比拟(在包含关系下的部分约束集上)。

但是,如果您更换

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>;

代码会编译。

关于c++ - 为什么same_as概念两次检查类型相等性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63748318/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com