在维护默认移动 /移动分配的同时,请确保派生的类实现静态方法

发布于 2025-01-19 04:38:39 字数 1384 浏览 2 评论 0原文

我想确保一些派生的类实现静态方法,并找到了这样的问题:确保派生的类实现静态方法最高答案使用CRTP在基类驱动器中使用static_assert解决问题,以确保模板参数类型实现static int foo(int int foo(int) )

但是,正如对答案的评论所指出的:“这个答案有一个小问题:写出灾难的结果是禁用了移动构造函数和移动分配运算符的产生。它还可以防止对象被琐碎地损坏。因此。因此。 ,在起作用的同时,该方法有缺点(此类弊端适用于其他特殊成员)。” - @matthieu m

有没有办法避免这种情况?我已经尝试将static_assert移动到base的成员函数和静态成员函数,但是在两种情况下,当派生时都不会产生编译时错误类未实现static int foo()。这是我一直在使用的代码(从上面进行调整,因此线程):

#include <type_traits>


template <class T>
class Base {
public:
    //~Base() //This works as expected! Compile error because Bad doesn't implement static int foo()
    //{
    //    static_assert(std::is_same<decltype(T::foo()), int>::value, "ERROR: No 'static int foo()' member provided");
    //}

    static void static_test() //This does not work. No compile time error.
    {
        static_assert(std::is_same<decltype(T::foo()), int>::value, "ERROR: No 'static int foo()' member provided");
    }
};

class Good : public Base<Good> {
public:
    static int foo() { return 42; };
};

class Bad : public Base<Bad> {
public:
    static double foo() { return 42; };
};

int main()
{
    Good g;
    Bad b;
}

I'd like to ensure some derived classes implement a static method and found this SO question: Ensure derived class implements static method The top answer uses CRTP to solve the issue with a static_assert in the base class destructor to ensure that the template argument type implements a static int foo(int).

However, as noted by a comment on the answer "There is a slight issue with this answer: writing out a destructor has the consequence of disabling the generation of a move constructor and move assignment operator. It also prevents the object from being trivially_destructible. So, while it works, there are downsides to the approach (and such downsides apply to other special members)." – @Matthieu M

Is there a way to avoid this downside? I've tried moving the static_assert to both a member function and static member function of Base, but in both cases it doesn't produce a compile-time error when a derived class doesn't implement static int foo(). Here's the code I've been working with (tweaked from the above SO thread):

#include <type_traits>


template <class T>
class Base {
public:
    //~Base() //This works as expected! Compile error because Bad doesn't implement static int foo()
    //{
    //    static_assert(std::is_same<decltype(T::foo()), int>::value, "ERROR: No 'static int foo()' member provided");
    //}

    static void static_test() //This does not work. No compile time error.
    {
        static_assert(std::is_same<decltype(T::foo()), int>::value, "ERROR: No 'static int foo()' member provided");
    }
};

class Good : public Base<Good> {
public:
    static int foo() { return 42; };
};

class Bad : public Base<Bad> {
public:
    static double foo() { return 42; };
};

int main()
{
    Good g;
    Bad b;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

拥抱我好吗 2025-01-26 04:38:39

您拥有的是班级需要实现的概念。您只需在类的定义之后检查一下,可能最容易使用static_assert

template<typename T>
static constexpr bool assert_is_fooable() {
    static_assert(std::is_same<decltype(T::foo()), int>::value, "ERROR: No 'static int foo()' member provided");
    static_assert(condition_2(), "ERROR: condition 2");
    // More specific error messages given above, this is always
    // true so it can be used in a static_assert
    return true;
}

class Good {
public:
    static int foo() { return 42; };
};

static_assert(assert_is_fooable<Good>());

即使该类未在其他任何地方使用,它甚至可以工作。您也可以将断言放在良好的地方,以期为其具有static int foo()而不是。

这允许类在琐碎的上破坏性,并且不会抑制移动构造函数或移动分配运算符,因为它实际上没有修改类。

What you have is a concept that the class needs to fulfil. You can simply check for it after the definition of the class, probably easiest with a static_assert:

template<typename T>
static constexpr bool assert_is_fooable() {
    static_assert(std::is_same<decltype(T::foo()), int>::value, "ERROR: No 'static int foo()' member provided");
    static_assert(condition_2(), "ERROR: condition 2");
    // More specific error messages given above, this is always
    // true so it can be used in a static_assert
    return true;
}

class Good {
public:
    static int foo() { return 42; };
};

static_assert(assert_is_fooable<Good>());

And it even works if that class is unused anywhere else. You could also put the assert at the place where Good is used that expects it to have static int foo() instead.

This allows the class to be trivially destructible and does not suppress the move constructor or move assignment operator, since it does not actually modify the class.

抱着落日 2025-01-26 04:38:39

不知道我是否正确理解了这个问题,但我认为你想得太复杂了。让编译器为您想要生成的特殊成员生成定义的解决方法是将它们声明为 default

struct foo {
    ~foo() {} // prevents the compiler to generate move constructor
    foo(foo&&) = default; // compiler generates a move constructor
}; 

Not sure if I understand the question correctly, but I think you are thinking too complicated. The workaround to let the compiler generate definition for special members you want to be generated is to declare them default:

struct foo {
    ~foo() {} // prevents the compiler to generate move constructor
    foo(foo&&) = default; // compiler generates a move constructor
}; 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文