我有该代码:
template<typename Type, typename... Extentions>
class Variable : virtual public GenericVar<Type>, public Extentions...
{
static_assert((std::is_base_of_v<GenericVar<Type>, Extentions> && ...), "Only virtual base of GenericVar<T> allowed as variadic.");
public:
template<typename... Args>
Variable(Type initValue, Args... args);
virtual ~Variable();
};
template<typename Type, typename... Extentions>
template<typename... Args>
Variable<Type,Extentions...>::Variable(Type initValue, Args... args) : GenericVar<Type>(), Extentions(args)...
{
this->value = initValue;
}
template<typename Type, typename... Extentions>
Variable<Type,Extentions...>::~Variable()
{
}
用法:
template<typename T>
using Constant = Variable<T, Immutable<T>, Forceable<T>>;
int main(int argc, char *argv[])
{
Variable<float, Forceable<float>> test2(1.2f,nullptr);
Constant<float> constant(4.578f, nullptr, nullptr);
Variable<quint32, Forceable<quint32>, ChangeCheckable<quint32>> value(45, nullptr, nullptr);
}
我想创建一个通用的、可扩展的类来构建我的所有 var 类型。
而且效果很好!但是...
我还没有找到避免构造函数中 nullptr 的方法。例如“强制”:
template<typename T>
class Forceable : virtual public GenericVar<T>
{
public:
Forceable(std::nullptr_t);
...
...
};
template<typename T>
Forceable<T>::Forceable(std::nullptr_t)
{
this->forced = false;
}
如果我删除它,我会收到此错误:
xxxxxxxxxxxxxxxx\main.cpp:16: erreur : mismatched argument pack lengths while expanding 'Extentions'
In file included from xxxxxxxxxxxxxxxx/Variables/Extention/Detectable.h:6,
from xxxxxxxxxxxxxxxx\main.cpp:5:
xxxxxxxxxxxxxxxx/Variables/Variable.h: In instantiation of 'Variable<Type, Extentions>::Variable(Type, Args ...) [with Args = {}; Type = float; Extentions = {Forceable<float>}]':
xxxxxxxxxxxxxxxx\main.cpp:16:49: required from here
xxxxxxxxxxxxxxxx/Variables/Variable.h:22:108: error: mismatched argument pack lengths while expanding 'Extentions'
22 | Variable<Type,Extentions...>::Variable(Type initValue, Args... args) : GenericVar<Type>(), Extentions(args)...
| ^~~
因为:在这种情况下,我猜是“Extentions(args)...”而不是“Extentions()” 我认为有一个解决方案......但我还没有找到它!
我想要:
template<typename T>
using Constant = Variable<T, Immutable<T>, Forceable<T>>;
int main(int argc, char *argv[])
{
Variable<float, Forceable<float>> test2(1.2f);
Constant<float> constant(4.578f);
Variable<quint32, Forceable<int>, ChangeCheckable<int>> value(45);
}
更深入的示例:
Variable<int, Forceable<int>, Boundable<int,int>, ChangeCheckable<int>, Validable<int>, RiseDefault<int, bool, Riseable> >
value3(0, nullptr, {-30,50}, nullptr, nullptr, 40, new Variable<bool, Riseable>(false,nullptr));
最佳答案
您可以为 Variable
创建一个构造函数,它将前 N 个 Extension
作为参数,并默认构造其余的。
这是一个不一定漂亮的实现
#include <tuple>
template <typename... T>
struct Variable: T... {
template <typename... U, size_t NumMissing = sizeof...(T) - sizeof...(U)>
Variable(U&&... u): Variable(std::make_index_sequence<NumMissing>{}, std::forward<U>(u)...) {}
private:
struct PrivateTag {};
template <typename... U, size_t... I>
Variable(std::index_sequence<I...>, U&&... u):
Variable(PrivateTag{},
std::forward<U>(u)...,
std::tuple_element_t<sizeof...(U) + I, std::tuple<T...>>()...) {}
template <typename... U>
Variable(PrivateTag, U&&... u): T(std::forward<U>(u))... {
static_assert(sizeof...(U) == sizeof...(T));
}
};
和测试代码
struct Ext {
Ext(int = 0) {}
};
struct Ext2 {
explicit Ext2(float = 0.0f) {}
};
// Extension that takes multiple constructor arguments
struct Ext3 {
explicit Ext3(int, int) {}
};
int main() {
// Default constructs both extensions
Variable<Ext, Ext2> x;
// Constructs Ext with value 1 and default constructs Ext2
Variable<Ext, Ext2> y(1);
// Constructs Ext with value 1 and Ext2 with value 1.f
Variable<Ext, Ext2> z(1, 1.f);
// Explicitly construct Ext3 since it takes multiple constructor aguments
Variable<Ext, Ext3> z(0, Ext3(1, 2));
}
此行为符合默认函数参数的工作方式。
关于c++ - 从可变参数继承并使用参数包: default constructor构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76797899/