使用C++;强制类实现一组方法的20个概念 我想知道C++中是否有一种方法(特别是C++ 20)来为类/结构编写一些接口。
例如,Java接口中有一个完全“抽象类”,用于将相关方法与空体分组: 界面动物 { 公共无效动物声(); 公开无效运行(); }使用C++;强制类实现一组方法的20个概念 我想知道C++中是否有一种方法(特别是C++ 20)来为类/结构编写一些接口。,c++,class,templates,c++20,c++-concepts,C++,Class,Templates,C++20,C++ Concepts,例如,Java接口中有一个完全“抽象类”,用于将相关方法与空体分组: 界面动物 { 公共无效动物声(); 公开无效运行(); } C++中,可以使用纯虚方法声明来实现相同的行为。 类动物 { 公众: 虚拟void animalSound()=0; 虚空运行()=0; }; 但是使用虚拟方法会有运行时开销,我对继承不感兴趣。 因此,这种运行时成本应该是不必要的。我只想对我的“动物”类/结构进行编译时检查 有了C++20的概念,我确信构建一个构造是可以实现的 可以应用于类以保证提供了一组特定的
C++中,可以使用纯虚方法声明来实现相同的行为。
类动物
{
公众:
虚拟void animalSound()=0;
虚空运行()=0;
};
但是使用虚拟方法会有运行时开销,我对继承不感兴趣。
因此,这种运行时成本应该是不必要的。我只想对我的“动物”类/结构进行编译时检查
有了C++20的概念,我确信构建一个构造是可以实现的
可以应用于类以保证提供了一组特定的方法
我想做的事情看起来有点像这样
template<typename Animal_> concept Animal =
requires()
{
(Animal_{}); // default constructable
(Animal_{}.animalSound());
(Animal_{}.run());
};
其中,
std::is_matching_concept
是我找不到的约束的占位符
我正在寻找最佳实践反馈和建议来解决我的问题
编辑-添加用例
// given the following code
template<typename Vector_, typename Float_=float> concept Vector =
requires()
{
(Vector_{}); // default constructable
(Vector_{}.X())->Float_;
(Vector_{}.Y())->Float_;
};
[[nodiscard]] constexpr auto Pow2(const auto x) noexcept
{
return x * x;
}
[[nodiscard]] constexpr auto LengthPow2(Vector auto vec) noexcept // the use of Vector
{
return Pow2(vec.X()) + Pow2(vec.Y());
}
// Now I want to implement a Vector
// and I want compile time checking, that I have no missed any properties
struct VectorImpl1
{
// EDITED: as @QuentinUK mentioned the static_assert should be in a public scope
// "If in the private part of a class the concepts
// can pass for private members which isn't what you'd want."
public:
// EDITED: as @DavisHerring mentioned this is the way to go
static_assert(Vector<VectorImpl1>);
public:
constexpr VectorImpl1() noexcept = default;
constexpr VectorImpl1(float x, float y) noexcept : x_(x), y_(y) {}
private:
float x_{};
float y_{};
public:
[[nodiscard]] constexpr float X() const noexcept
{ return x_; }
[[nodiscard]] constexpr float Y() const noexcept
{ return y_; }
};
struct VectorImpl2
{
public:
static_assert(Vector<VectorImpl2>);
public:
constexpr VectorImpl2() noexcept = default;
constexpr VectorImpl2(float rad, float length) noexcept : rad_(rad), length_(length) {}
private:
float rad_{};
float length_{};
public:
[[nodiscard]] constexpr float X() const noexcept
{ return CalcX(rad_, length_); }
[[nodiscard]] constexpr float Y() const noexcept
{ return CalcY(rad_, length_); }
};
//给定以下代码
模板概念向量=
需要()
{
(Vector_{});//默认可构造
(Vector_{}.X())->Float;
(Vector_{}.Y())->Float;
};
[[nodiscard]]constexpr auto Pow2(const auto x)无例外
{
返回x*x;
}
[[nodiscard]]constexpr auto LengthPow2(Vector auto vec)无例外//使用Vector
{
返回Pow2(向量X())+Pow2(向量Y());
}
//现在我想实现一个向量
//我需要编译时检查,确保没有遗漏任何属性
结构向量mpl1
{
//编辑:正如@QuentinUK提到的,静态断言应该在公共范围内
//“如果在类的私有部分中
//可以通过私人会员,这不是您想要的。”
公众:
//编辑:正如@DavisHerring提到的,这是一条路要走
静态(向量);
公众:
constexpr VectorImpl1()noexcept=default;
constexpr VectorImpl1(float x,float y)noexcept:x_ux,y_ux(y){
私人:
浮点数x{};
浮动y{};
公众:
[[nodiscard]]constexpr float X()const noexcept
{返回x;}
[[nodiscard]]constexpr float Y()const noexcept
{返回y;}
};
结构向量mpl2
{
公众:
静态(向量);
公众:
constexpr VectorImpl2()noexcept=default;
constexpr VectorImpl2(float-rad,float-length)无例外:rad(rad),length(length){
私人:
浮动半径{};
浮动长度{};
公众:
[[nodiscard]]constexpr float X()const noexcept
{返回CalcX(rad,length);}
[[nodiscard]]constexpr float Y()const noexcept
{return CalcY(rad,length);}
};
可以,问题是为什么要这样做。
如果您的类型没有执行预期的操作,您将得到一个编译错误,对吗
如果出于某种原因希望在同一标头中获得编译错误,可以执行以下操作:
template <typename ...>
using void_t = void; // available since c++17 in std
template <typename T>
using cow_test = void_t<
decltype(std::declval<T>().moo(0)),
decltype(std::declval<T>().chew(0))
>;
class cow {
public:
void moo(int);
void chew(int);
};
using test_cow = cow_test<cow>;
class cat {
public:
void meaw(int);
void chew(int);
};
using test_cat = cow_test<cat>;
不过,我怀疑您想要的是根据这些信息采取行动:基本上-如果我的类可以moo()
-moo,否则meaw
这是可以实现的,在概念出现之前,通过使用
检测习惯用法,我建议看一下:或者读一下这不是CRTP的目的吗?“所以这个运行时成本应该是不必要的。我只想对我的“动物”类/结构进行编译时检查。”我不理解这里的用例。你会使用某种多态性吗?也就是说,您是否要将该类型传递给不知道确切类型的对象?如果没有,那么就没有什么真正需要验证的了。如果是这样,那么您应该考虑一些接口,这些接口将接收并使用实现所述接口的对象。仅验证声明是否与概念匹配是没有意义的。返回类型测试std::is_matching_concept
拼写为C
,不过您必须将静态断言
放在类后。静态断言可以在类内。(但是如果在类的私有部分,概念可以传递给私有成员,这不是您想要的。)
template <typename ...>
using void_t = void; // available since c++17 in std
template <typename T>
using cow_test = void_t<
decltype(std::declval<T>().moo(0)),
decltype(std::declval<T>().chew(0))
>;
class cow {
public:
void moo(int);
void chew(int);
};
using test_cow = cow_test<cow>;
class cat {
public:
void meaw(int);
void chew(int);
};
using test_cat = cow_test<cat>;
r #1) C++
x86-64 gcc 10.1
Compiler options...
1
<Compilation failed>
x86-64 gcc 10.1 - 364ms
#1 with x86-64 gcc 10.1
<source>: In substitution of 'template<class T> using cow_test = void_t<decltype (declval<T>().moo(0)), decltype (declval<T>().chew(0))> [with T = cat]':
<source>:26:30: required from here
<source>:8:33: error: 'class cat' has no member named 'moo'
8 | decltype(std::declval<T>().moo(0)),
| ~~~~~~~~~~~~~~~~~~^~~