C++ 用C+清理静态接口+;20个概念
我试图使用C++20概念创建一个静态接口,下面的代码似乎可以完成这项工作:C++ 用C+清理静态接口+;20个概念,c++,c++20,concept,C++,C++20,Concept,我试图使用C++20概念创建一个静态接口,下面的代码似乎可以完成这项工作: template <class FOO> concept FooConcept = requires { static_cast<void (FOO::*)(int)>(&FOO::operator()); static_cast<void (FOO::*)(char)>(&FOO::operator()); }; 或 模板 concept FooCo
template <class FOO>
concept FooConcept = requires {
static_cast<void (FOO::*)(int)>(&FOO::operator());
static_cast<void (FOO::*)(char)>(&FOO::operator());
};
或
模板
concept FooConcept=std::invocable&&std::invocable;
但是,由于隐式转换,这些方法不起作用(请参阅)。
是否有更好、更“语义”的方法来表达此约束?使用一些帮助程序,以及非
final
类,您可以执行以下操作:
template <typename T>
struct DeletedOperator : T
{
using T::operator ();
template <typename ... Ts>
void operator()(Ts&&...) = delete;
template <typename ... Ts>
void operator()(Ts&&...) const = delete;
};
template <class FOO>
concept FooConcept = requires (DeletedOperator<FOO> foo, int i, char c) {
{ foo(i) } -> std::same_as<void>;
{ foo(c) } -> std::same_as<void>;
};
模板
结构删除运算符:T
{
使用T::operator();
模板
void操作符()(Ts&&…)=delete;
模板
void运算符()(Ts&…)const=delete;
};
模板
concept FooConcept=requires(DeletedOperator foo,int i,char c){
{foo(i)}->std::与相同;
{foo(c)}->std::与相同;
};
我认为我们可以通过调整helper来摆脱非
final
约束。“当且仅当此类类重载运算符()两次:分别使用int参数和char参数时,FooConcept会得到满足。”-不完全是:如果但非仅当:如果FOO
具有模板运算符,也会得到满足(例如template void operator()(T){}
)当然,我的错误!我会立即解决这个问题。但它仍然满足我的要求:它表现为一个静态接口!是的,它们反映了受概念约束的模板如何实际使用该类型。例如,拥有T.foo(0);
表示模板可以安全地执行t.foo(0)
。在这种情况下,是否转换0是非常不相关的。您可以查看C++0x概念的历史记录,以了解为什么以您尝试的方式指定接口的原始方向与当前概念的方向不同。这些会议和讨论的结果将比我以往任何时候都更能说明问题为什么。好吧,你可以给丑起个名字:@fdev,我没有提到任何特别的东西,但我知道概念的最初化身已经有了相当长的历史。对于一个大的功能,到死胡同,然后以完全不同的形式回来,涉及到很多讨论,所以它更多的是一个一般性的参考。我不是我试图大惊小怪地指出,当前的化身是为了模拟该类型的用户而不是实现者,因为心理模型是完全不同的。我对你的想法投了赞成票,尽管我不完全理解!你介意详细阐述一下吗?无论如何,它并没有产生想要的行为:例如,如果类FOO
使用默认参数重载operator()
(例如,void operator()(int i,double d=0.);
而不是void operator()(int i);
),那么您定义的FooConcept
就不会抱怨了,而我正确地建议的实现会抱怨。此外,尽管问题中没有明确说明,但我希望为一般成员函数提供一种通用的方法,而不仅仅限于operator()
functions!想法是模板删除重载避免转换,因为它们完全匹配。
template <class FOO>
concept FooConcept = std::invocable<FOO, int> && std::invocable<FOO, char>;
template <typename T>
struct DeletedOperator : T
{
using T::operator ();
template <typename ... Ts>
void operator()(Ts&&...) = delete;
template <typename ... Ts>
void operator()(Ts&&...) const = delete;
};
template <class FOO>
concept FooConcept = requires (DeletedOperator<FOO> foo, int i, char c) {
{ foo(i) } -> std::same_as<void>;
{ foo(c) } -> std::same_as<void>;
};