【问题标题】:Force static method in class based on interface in C++基于C++接口的类中的强制静态方法
【发布时间】:2021-01-25 12:14:14
【问题描述】:

我正在制作一个向量类,它可以选择将分配器作为模板参数。为了确保用户定义的分配器与向量一起使用,我提供了一个接口,该接口设置了给定分配器的最低要求。由于分配器只是用于分配和释放,它没有成员变量,所有方法都是静态的。有没有办法确保任何实现都有一组给定的静态方法?我知道你不能同时拥有静态和虚拟的方法,但我本质上希望从 base_allocator 派生的任何分配器都具有一组方法,并且这些方法是静态的。 简而言之:你能解决 c++ 中的 virtual static 矛盾吗?

这是我当前的代码:

// in namespace mem_core
// Interface for usage of custom allocators with the custom:: namespace containers.
template <typename T>
class base_allocator {
public:
    using T_ptr = T*;
    using T_ref = T&;

    virtual T_ptr address(const T_ref value);

    // memory methods should allocate for amount elements of type T
    virtual void deallocate(T_ptr const ptr, const size_t& count) = 0;
    virtual T_ptr allocate(const size_t& amount) = 0;
};

_MEMORY_CORE_END_ // namespace mem_core }

#undef _MEMORY_CORE_BEGIN_
#undef _MEMORY_CORE_END_

// default allocator CLASS TEMPLATE
template <typename T>
class allocator : public mem_core::base_allocator<T> {
public:

    using value_type = T;
    using T_ptr = T*;
    using T_ref = T&;

    static T_ptr address(T_ref value) noexcept {
        return mem_core::addressof<T>(value);
    }

    static void deallocate(T_ptr const ptr, const size_t& count) {
        mem_core::deallocate<T>(ptr, count);
    }

    static T_ptr allocate(const size_t& amount) {
        return mem_core::allocate<T>(amount);
    }
};

这当然有效,但不能保证用户定义的分配器使虚方法成为静态的,因为这是分配器在向量类中工作的要求。 例如像这样:

template <typename T, typename alloc_type = allocator<T>>
class vector {
public:

    using iterator = vector_iterator<vector<T, alloc_type>>;

    using T_ptr = T*;
    using T_ref = T&;

    using value_type = T;
private:
    T_ptr m_data;
    size_t m_size;
    size_t m_capacity;
public:
    vector() : m_data(nullptr), m_size(0), m_capacity(0) noexcept {};

    vector(const size_t& initial_cap) : m_size(0) {
        m_data = alloc_type::allocate(m_capacity); // Requires static allocate method
        m_capacity = initial_cap;
    }
// rest of vector class ...

【问题讨论】:

  • "简而言之:你能解决 c++ 中的虚拟静态矛盾吗?" 不能。但是你可以使用静态多态(即模板) .

标签: c++ inheritance polymorphism static-methods virtual-functions


【解决方案1】:

可能需要使用SFINAE 将某些方法定义为静态的类。下面的例子使用了 C++20 的概念,但是通过一些工作可以适应使用纯 SFINAE,因为这是这里唯一需要的东西。这个例子定义了一个概念has_static_methods,它要求一个类将“function”和“function2”都实现为静态方法。非静态方法,无论是否虚拟,都会失败:

#include <iostream>
#include <type_traits>

template<typename T> struct is_function : public std::false_type {};

template<typename Ret, typename ...Args>
struct is_function<Ret (*)(Args...)> : public std::true_type {};

struct not_static {

    void function();
    static void function2();
};

struct is_static {
    static void function();
    static void function2();
};

template<typename T>
concept has_static_methods = is_function<decltype(&T::function)>::value &&
    is_function<decltype(&T::function2)>::value;

// Ok's template parameter type must implement both static methods.

template<has_static_methods T> void ok()
{
}

int main()
{
    ok<is_static>();        // OK
    ok<not_static>();       // Error, unsatisfied contsraint.
    return 0;
}

通过一些额外的工作,可以强制执行具有特定签名的静态方法。

现在,请记住,这并不能真正阻止任何人使用非静态方法定义子类。这要求任何作为参数传递给模板的类都满足此约束。

【讨论】:

  • 谢谢!这似乎可以解决问题。我忘了提到我正在尝试保持无依赖,包括 STL,但我想这就像从 实现所需的功能一样简单,以使一切正常。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2011-02-17
  • 2010-10-31
  • 2018-09-16
  • 2010-09-06
  • 2015-06-15
  • 2011-01-17
  • 2014-01-01
相关资源
最近更新 更多