C++ 将默认值列表传递给模板类
不确定这是否可以使用模板完成,但我想尝试一下 我有一个模板类,它接受任何结构,存储并返回它。此外,我需要一个接口,可以在任何时候请求时重置结构的数据C++ 将默认值列表传递给模板类,c++,templates,C++,Templates,不确定这是否可以使用模板完成,但我想尝试一下 我有一个模板类,它接受任何结构,存储并返回它。此外,我需要一个接口,可以在任何时候请求时重置结构的数据 #define MYDEFAULT {1,2,3} template < typename ITEM, ITEM Default> class myClass{ public: myClass(ITEM item) : _item(item) {} const ITEM* get(){ return
#define MYDEFAULT {1,2,3}
template < typename ITEM, ITEM Default>
class myClass{
public:
myClass(ITEM item) : _item(item) {}
const ITEM* get(){
return &_item;
}
void reset(){
_item = Default;
}
ITEM _item;
};
// Set to default when instantiated
myClass<myStruct, MYDEFAULT> ABC(MYDEFAULT);
最初xxx为10,调用reset后为5。这是可行的,所以对于POD或类类型来说似乎是不可能的
EDIT2:似乎都是关于非类型模板参数的。
因此,在使用结构时无法绕过trait。作为可行的解决方案,您可以使用trait类,如以下工作示例所示:
#include<cassert>
struct S {
int i;
};
template<typename T>
struct Traits {
static constexpr auto def() { return T{}; }
};
template<>
struct Traits<S> {
static constexpr auto def() { return S{42}; }
};
template <typename ITEM>
class myClass {
public:
myClass(): _item(Traits<ITEM>::def()) {}
myClass(ITEM item): _item(item) {}
const ITEM* get() {
return &_item;
}
void reset() {
_item = Traits<ITEM>::def();
}
ITEM _item;
};
int main() {
myClass<S> ABC{};
myClass<int> is;
assert((ABC.get()->i == 42));
assert((*is.get() == 0));
}
无论如何,traits可以很容易地一次提供更多类型和函数。您可以使用数据结构模拟它,其中的数据成员类型为
std::array
下面是一个简单的工作示例:
#include<cstddef>
#include<array>
#include<cassert>
template<typename T, T... I>
struct S {
S(): arr{ I... } {}
S(const T (&val)[sizeof...(I)]) {
for(std::size_t i = 0; i < sizeof...(I); ++i) {
arr[i] = val[i];
}
}
const T * get() {
return arr.data();
}
void reset() {
arr = { I... };
}
private:
std::array<T, sizeof...(I)> arr;
};
int main() {
S<int, 1, 3, 5> s{{ 0, 1, 2 }};
assert(s.get()[1] == 1);
s.reset();
assert(s.get()[1] == 3);
}
#包括
#包括
#包括
模板
结构{
S():arr{I..}{}
(常数和值)[sizeof…(I)]){
对于(std::size_t i=0;i
我不确定我是否完全理解了您的要求,但示例中的接口与问题中的接口非常接近,实现细节不应影响您的类的用户。这很有效,谢谢您。但我正在寻找一种不需要定义另一个特征模板的方法。我很乐意以某种方式将结构直接传递给我的类;以某种方式利用模板功能。还是真的没有办法?“我的意思是它只是一个替代品,不是吗?”wanderameise我在添加另一个答案。让我知道它是否适合你。我还是不去碰这个,因为我发现它是一个有效的替代方案。是的,它是一个完全有效的替代方案,已经证明可以很好地工作!我不确定我到底得到了你想要的。不管怎么说,我又增加了一个答案,可能适合你的需要。让我知道它是否沿着正确的方向运行至少…:-)好的,但是我必须将默认值存储在一个数组中,这不是我想要的,因为这与我在第一次编辑中发布的没有额外空间占用的解决方案不同。不过,谢谢你,我学到了很多关于模板的知识。我想对于结构类型没有简单的解决方案…@wanderameise否,默认值(
I…
)不存储在任何地方,它们是一个参数包,一旦实例化,它就是类的一部分。从上面的例子可以看出,您可以自由地使用一组不同的值来初始化类,然后调用reset并发现默认值已放入数组中?另外,T是一个整数类型,但我需要维护一个结构。@wanderameise不,对不起,这不是我的本意。您可以自由使用sss{3,10,42}代码>。它们是要使用的初始值,仅此而已。当然,如果在示例中更改它们,则必须相应地更新main
中的assert
s?当初始化S时,是否可以传递结构默认值:{1,2,3,4,5}?
template<typename T>
constexpr auto def() { return T{}; }
template<>
constexpr auto def<S>() { return S{42}; }
#include<cstddef>
#include<array>
#include<cassert>
template<typename T, T... I>
struct S {
S(): arr{ I... } {}
S(const T (&val)[sizeof...(I)]) {
for(std::size_t i = 0; i < sizeof...(I); ++i) {
arr[i] = val[i];
}
}
const T * get() {
return arr.data();
}
void reset() {
arr = { I... };
}
private:
std::array<T, sizeof...(I)> arr;
};
int main() {
S<int, 1, 3, 5> s{{ 0, 1, 2 }};
assert(s.get()[1] == 1);
s.reset();
assert(s.get()[1] == 3);
}