trb*_*abb 8 c++ type-traits c++-concepts c++20
std::common_type<T1, ..., TN>T1是 C++ 中的一个辅助模板,它可以找到所有...TN都可以隐式转换为的通用类型。
根据 C++ 规范,如果某些条件适用,用户可以专门化std::common_type<T1,T2>,并且:
std::common_type<T1, T2>::type并且std::common_type<T2, T1>::type必须表示相同的类型。
然而,common_type<T1, T2>对于用户类型来说,可能是一个非常复杂的专业化,T1并且T2:
namespace std {
template <typename T1, complicated_constraint_of<T1> T2, ...>
struct common_type<complicated_expression_of<T1, ...>, complicated_expression_of<T2, ...>> {
using type = complicated_type_expression_of<T1,T2>;
};
}
Run Code Online (Sandbox Code Playgroud)
一般来说,约束表达式不一定是对称的(例如,我们可以指定 是T2的底T1)。这意味着为了保持对称性,我们需要用T1和T2反转来重写整个特化,但在不犯任何错误的情况下做到这一点是极其困难和脆弱的。
如何common_type<T1,T2>为我自己的类型稳健地定义 的交换特化?
这是我想出的 C++20 解决方案:
// define concept of `common_type<A,B>` existing
template <typename A, typename B>
concept has_in_common_ordered = requires { common_type<A,B>::type; };
namespace std {
// define common_type<A,B> if common_type<B,A>::type exists:
template <typename A, has_in_common_ordered<A> B>
struct common_type<A,B> : public common_type<B,A> {};
}
Run Code Online (Sandbox Code Playgroud)
现在,有了上面的内容,应该可以编译以下内容:
struct X {};
struct Y {};
namespace std {
template<>
struct common_type<X,Y> {
using type = X; // or whatever
};
}
int main() {
// even though we only specialized for one ordering,
// both orderings now exist:
std::common_type<X,Y>::type a;
std::common_type<Y,X>::type b;
}
Run Code Online (Sandbox Code Playgroud)
我认为以下两种情况之一是可能的:
std::common_type。我等待有人在评论中告诉我它是哪一个。;)