鉴于:
#include <concepts>
#include <iostream>
template<class T>
struct wrapper;
template<std::signed_integral T>
struct wrapper<T>
{
wrapper() = default;
void print()
{
std::cout << "signed_integral" << std::endl;
}
};
template<std::integral T>
struct wrapper<T>
{
wrapper() = default;
void print()
{
std::cout << "integral" << std::endl;
}
};
int main()
{
wrapper<int> w;
w.print(); // Output : signed_integral
return 0;
}
Run Code Online (Sandbox Code Playgroud)
从上面的代码中,int符合std::integral和std::signed_integral概念。
令人惊讶的是,这会在 GCC 和 MSVC 编译器上编译并打印“signed_integral”。我原以为它会失败,并出现“模板专业化已经定义”的错误。
好的,这是合法的,足够公平,但为什么std::signed_integral选择而不是std::integral?当多个概念符合模板参数的条件时,标准中是否定义了任何规则来选择模板特化?
从 libstdc++<concepts>头文件:
namespace ranges
{
namespace __cust_swap
{
template<typename _Tp> void swap(_Tp&, _Tp&) = delete;
Run Code Online (Sandbox Code Playgroud)
从 MS-STL<concepts>标头:
namespace ranges {
namespace _Swap {
template <class _Ty>
void swap(_Ty&, _Ty&) = delete;
Run Code Online (Sandbox Code Playgroud)
我从未遇到过= delete;要禁止调用复制/移动赋值/ctor 的上下文之外的情况。
我很好奇这是否有必要,所以我= delete;像这样注释了库中的部分:
// template<typename _Tp> void swap(_Tp&, _Tp&) = delete;
Run Code Online (Sandbox Code Playgroud)
看看下面的测试用例是否编译。
#include <concepts>
#include <iostream>
struct dummy {
friend void swap(dummy& a, dummy& b) {
std::cout << "ADL" << std::endl;
}
};
int main()
{
int a{};
int …Run Code Online (Sandbox Code Playgroud) 来自 ISO 标准(准确地说是 N4860)的std::pair概要:
constexpr explicit(see below) pair(const T1& x, const T2& y); // first constructor
template<class U1, class U2>
constexpr explicit(see below) pair(U1&& x, U2&& y); // second constructor
Run Code Online (Sandbox Code Playgroud)
我似乎找不到任何理由为什么第一个构造函数应该与完美转发构造函数一起定义。完美的转发构造函数是否足以处理复制、移动两种情况?在哪种情况下,第一个构造函数在重载决议中获胜?