基于 C++ 中的接口在 class 中强制静态方法
Force static method in class based on interface in C++
我正在制作一个 vector-class,它可以选择将分配器作为模板参数。为了确保用户定义的分配器与向量一起工作,我提供了一个接口来设置给定分配器的最低要求。由于分配器只是用于分配和释放,它没有成员变量,所有方法都是静态的。有没有办法确保任何实现都有一组给定的方法,这些方法也是静态的?我知道你不能让一个方法同时是静态的和虚拟的,但我本质上希望从 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);
}
};
这当然有效,但不能保证用户定义的分配器已将虚拟方法设为静态,因为这是分配器在 vector-class 中工作的要求。
例如像这样:
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 ...
可能需要 class 某些方法使用 SFINAE 定义为静态。下面的示例使用了 C++20 的概念,但稍作修改就可以使用纯 SFINAE,因为这是这里唯一需要的东西。此示例定义了一个概念 has_static_methods
,它需要 class 将“function”和“function2”都实现为静态方法。 Non-static 方法,虚拟与否,失败:
#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;
}
通过一些额外的工作,可以强制执行具有特定签名的静态方法。
现在请记住,这并不能真正阻止任何人使用 non-static 方法定义 subclass。这需要作为参数传递给模板的任何 class 满足此约束。
我正在制作一个 vector-class,它可以选择将分配器作为模板参数。为了确保用户定义的分配器与向量一起工作,我提供了一个接口来设置给定分配器的最低要求。由于分配器只是用于分配和释放,它没有成员变量,所有方法都是静态的。有没有办法确保任何实现都有一组给定的方法,这些方法也是静态的?我知道你不能让一个方法同时是静态的和虚拟的,但我本质上希望从 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);
}
};
这当然有效,但不能保证用户定义的分配器已将虚拟方法设为静态,因为这是分配器在 vector-class 中工作的要求。 例如像这样:
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 ...
可能需要 class 某些方法使用 SFINAE 定义为静态。下面的示例使用了 C++20 的概念,但稍作修改就可以使用纯 SFINAE,因为这是这里唯一需要的东西。此示例定义了一个概念 has_static_methods
,它需要 class 将“function”和“function2”都实现为静态方法。 Non-static 方法,虚拟与否,失败:
#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;
}
通过一些额外的工作,可以强制执行具有特定签名的静态方法。
现在请记住,这并不能真正阻止任何人使用 non-static 方法定义 subclass。这需要作为参数传递给模板的任何 class 满足此约束。