英文:
How to change/set template parameter based on type?
问题
I want to create a static class, which will act as a fixed-size memory allocator.
让我们看一个简化的示例:
struct A {};
struct B {};
template<class T, std::size_t MaxNumObjects>
class InternalContainer
{
public:
static constexpr std::size_t maxObjects = MaxNumObjects;
static T* createObject()
{
return ::new(&objects[idx++]) T;
}
static T* releaseObject() { /*...*/ };
private:
using buffer_t = std::aligned_storage_t<sizeof(T), alignof(T)>;
static buffer_t objects[maxObjects];
static std::size_t idx;
};
A* a = InternalContainer<A, 2>::createObject();
B* b = InternalContainer<B, 5>::createObject();
如何根据类型预定义容器的最大大小?
// 将被替换为 "InternalContainer<A, 2>"
A* a = MyContainer<A>::createObject();
// 将被替换为 "InternalContainer<B, 5>"
B* b = MyContainer<B>::createObject();
我尝试了类似以下的方法,但它不起作用:
template<class T>
using MyContainer = InternalContainer<A, 2>;
template<class T>
using MyContainer = InternalContainer<B, 5>;
英文:
I want to create a static class, which will act as fixed size memory allocator.
Lets look at this simplified example:
struct A {};
struct B {};
template<class T, std::size_t MaxNumObjects>
class InternalContainer
{
public:
static constexpr std::size_t maxObjects = MaxNumObjects;
static T* createObject()
{
return ::new(&objects[idx++]) T;
}
static T* releaseObject() { /*...*/ };
private:
using buffer_t = std::aligned_storage_t<sizeof(T), alignof(T)>;
static buffer_t objects[maxObjects];
static std::size_t idx;
};
A* a = InternalContainer<A, 2>::createObject();
B* b = InternalContainer<B, 5>::createObject();
How can I predefine the maximum size of the container based on type?
// will be replaced "InternalContainer<A, 2>"
A* a = MyContainer<A>::createObject();
// will be replaced "InternalContainer<B, 5>"
B* b = MyContainer<B>::createObject();
I have tried something like this, but it does not work:
template<class T>
using MyContainer = InternalContainer<A, 2>;
template<class T>
using MyContainer = InternalContainer<B, 5>;
答案1
得分: 8
Sure, here's the translated code portion:
> 如何根据类型预定义容器的最大大小?
您有几个选项。
最简单的方法是为默认类型(即`A`、`B`)提供专门化。
template <class T> struct MyContainer;
// 为 A 进行专门化
template <> struct MyContainer<A> {
using type = InternalContainer<A, 2>;
};
// 为 B 进行专门化
template <> struct MyContainer<B> {
using type = InternalContainer<B, 5>;
};
// ...以此类推!
// 辅助别名
template <class T>
using MyContainer_t = typename MyContainer<T>::type;
static_assert(std::is_same_v<MyContainer_t<A>, InternalContainer<A, 2>>);
[在godbolt.org中查看在线演示](https://gcc.godbolt.org/z/6n51jcKhM)
----------
另外,您还可以使用 [`if constexpr`][1](需要 [tag:C++17] 或更高版本)来尝试以下操作:
#include <type_traits>
template <class T>
constexpr auto typeHelper()
{
// 以下需要 InternalContainer<T, N> 可以默认构造!
if constexpr (std::is_same_v<T, A>) return InternalContainer<A, 2>{};
else if constexpr (std::is_same_v<T, B>) return InternalContainer<B, 5>{};
}
template <class T>
using MyContainer = decltype(typeHelper<T>());
A* a = MyContainer<A>::createObject(); // 将被替换为 InternalContainer<A, 2>
B* b = MyContainer<B>::createObject(); // 将被替换为 InternalContainer<B, 5>
[在godbolt.org中查看在线演示](https://gcc.godbolt.org/z/vPj9ccTvf)
----------
此外,您还可以使用 [`std::conditional_t`][2],如下所示:
#include <type_traits> // std::conditional_t
template <class T>
using MyContainer = std::conditional_t<std::is_same_v<T, A>, InternalContainer<A, 2>,
std::conditional_t<std::is_same_v<T, B>, InternalContainer<B, 5>,
/如果类型既不是A也不是B,则默认情况/ void>
>;
[在godbolt.org中查看在线演示](https://gcc.godbolt.org/z/oKW6GKj7K)
[1]: https://en.cppreference.com/w/cpp/language/if
[2]: https://en.cppreference.com/w/cpp/types/conditional
英文:
> How can I predefine the maximum size of the container based on type?
You have several options here.
The easiest, would be providing a specialization for the default types (i.e. A
, B
)
template <class T> struct MyContainer;
// specialization for A
template <> struct MyContainer<A> {
using type = InternalContainer<A, 2>;
};
// specialization for B
template <> struct MyContainer<B> {
using type = InternalContainer<B, 5>;
};
// ... so on!
// Helper alias
template <class T>
using MyContainer_t = typename MyContainer<T>::type;
static_assert(std::is_same_v<MyContainer_t<A>, InternalContainer<A, 2>>);
Alternatively, using if constexpr
(requires [tag:C++17] or higher) you might be able to do something like as follows:
#include <type_traits>
template <class T>
constexpr auto typeHelper()
{
// following requires the InternalContainer<T, N> be default constructible!!
if constexpr (std::is_same_v<T, A>) return InternalContainer<A, 2>{};
else if constexpr (std::is_same_v<T, B>) return InternalContainer<B, 5>{};
}
template <class T>
using MyContainer = decltype(typeHelper<T>());
A* a = MyContainer<A>::createObject(); // will be replaced b InternalContainer<A, 2>
B* b = MyContainer<B>::createObject(); // will be replaced b InternalContainer<B, 5>
Alternatively, using std::conditional_t
you could do also
#include <type_traits> // std::conditional_t
template <class T>
using MyContainer = std::conditional_t<std::is_same_v<T, A>, InternalContainer<A, 2>,
std::conditional_t<std::is_same_v<T, B>, InternalContainer<B, 5>,
/*Default case if types are not A nor B*/ void>
>;
答案2
得分: 6
这可以通过显式专门化变量模板轻松实现,例如:
struct A {};
struct B {};
struct C {};
// 所有 InternalContainers 的默认大小
template<class T>
constexpr std::size_t InternalContainerDefaultSize = 64;
// 专门为 A 的情况
template<>
constexpr std::size_t InternalContainerDefaultSize<A> = 2;
// 专门为 B 的情况
template<>
constexpr std::size_t InternalContainerDefaultSize<B> = 5;
template<class T, std::size_t MaxNumObjects = InternalContainerDefaultSize<T>>
class InternalContainer {
/* ... */
};
InternalContainer<A> aContainer; // 大小将为 2
InternalContainer<B> bContainer; // 大小将为 5
InternalContainer<C> cContainer; // 大小将为 64
// 默认大小可以通过显式指定另一个大小来覆盖
InternalContainer<A, 10> aContainer; // 大小将为 10
英文:
This can be easily accomplished by explicitly specializing a variable template, e.g.:
struct A {};
struct B {};
struct C {};
// default size for all InternalContainers
template<class T>
constexpr std::size_t InternalContainerDefaultSize = 64;
// specialization for A
template<>
constexpr std::size_t InternalContainerDefaultSize<A> = 2;
// specialization for B
template<>
constexpr std::size_t InternalContainerDefaultSize<B> = 5;
template<class T, std::size_t MaxNumObjects = InternalContainerDefaultSize<T>>
class InternalContainer {
/* ... */
};
InternalContainer<A> aContainer; // size will be 2
InternalContainer<B> bContainer; // size will be 5
InternalContainer<C> cContainer; // size will be 64
// default size can be overriden by explicitly specifying another size
InternalContainer<A, 10> aContainer; // size will be 10
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论