C++ 使用C++;模板
我有一个包装类。任何T或从T派生的对象都应可转换到此包装器 我还希望“Someclass”的任何对象或从“Someclass”派生的对象都可以转换为包装器。这两种情况下的实施需要分开。我怎样才能做到这一点 以下是我想要的行为:C++ 使用C++;模板,c++,templates,template-argument-deduction,C++,Templates,Template Argument Deduction,我有一个包装类。任何T或从T派生的对象都应可转换到此包装器 我还希望“Someclass”的任何对象或从“Someclass”派生的对象都可以转换为包装器。这两种情况下的实施需要分开。我怎样才能做到这一点 以下是我想要的行为: class SomeClass; template <typename T> class Wrapper { public: Wrapper(const T & val) { } template <typ
class SomeClass;
template <typename T>
class Wrapper
{
public:
Wrapper(const T & val)
{
}
template <typename E>
Wrapper(const E & val)
{
static_assert(std::is_base_of<T, E>::value,"Wrapped object needs to be of type T or a type derived from T");
// Some implementation
}
// Is it possible to combine the above 2 constructors into a single
// one? That would help too...
// Can't use SomeClass directly as type because in case of derived
// type of SomeClass, I want the exact type for downstream processing
// into another template call
template <typename E> // ??
Wrapper(const E & val)
{
static_assert(std::is_base_of<SomeClass, E>::value,"Wrapped object needs to be of type SomeClass or a type derived from SomeClass");
// another implementation
}
};
class-SomeClass;
模板
类包装器
{
公众:
包装器(常数T&val)
{
}
模板
包装器(常数E&val)
{
static_assert(std::is_base_of::value,“包装的对象需要是T类型或从T派生的类型”);
//一些实现
}
//是否可以将上述两个构造函数组合成一个单独的构造函数
//一个?那也会有帮助。。。
//无法将SomeClass直接用作类型,因为在派生的情况下
//SomeClass的类型,我想要下游处理的确切类型
//进入另一个模板调用
模板//??
包装器(常数E&val)
{
static_assert(std::is_base_of::value,“包装的对象需要是SomeClass类型或从SomeClass派生的类型”);
//另一个实现
}
};
不确定我是否能够正确地表达我的问题。非常感谢您提供的任何帮助……让我们从您目前拥有的不起作用的原因开始。模板函数(构造函数也是)由其签名标识。该签名包括模板参数是什么(类型、非类型、模板)、它们的顺序,以及函数参数和返回类型(构造函数没有返回类型,但这与我们试图实现的目标无关)。所以你要做的是,两次声明同一个constructor!在考虑定义之前,您有一个重复的声明,这当然是不允许的 那么我们能做什么呢?我们可以向每个构造函数添加参数。如果它能区分它们,它们就可以共存。但共存是不够的,我们希望以不同的方式对待它们。我们希望为从T派生的类选择第一个模板化的c'tor,为从
SomeClass
派生的类选择第二个模板化的c'tor。我们能做到吗?是的,我们可以。如果我们使我们将添加的模板参数取决于我们的条件,并且在不满足条件时替换失败,那么将从考虑中删除该重载。那太棒了
因此,将所有这些付诸实践:
template <typename E, std::enable_if_t<!std::is_same<SomeClass,T>::value &&
std::is_convertible<E*, T*>::value>* = nullptr>
Wrapper(const E & val)
{
}
template <typename E, std::enable_if_t<std::is_convertible<E*, SomeClass*>::value>* = nullptr>
Wrapper(const E & val)
{
}
template::value>*=nullptr>
包装器(常数E&val)
{
}
模板
包装器(常数E&val)
{
}
那么,上面所说的是什么呢?它添加了另一个带有默认参数的模板参数。它是有条件地这样做的,如果在替换过程中不满足条件,则“坏”的c'tor的签名是错误的。在过载解决方案中不会考虑这一点
我还冒昧地改变了你的状况。您可能只希望接受公开派生自
T
和SomeClass
的类。通过std::is_convertible
可以更好地表达这一点<代码>标准::is_base_of也将允许私有和不明确的多重继承。我还确保在T
是SomeClass
的情况下,我们不会再得到两个冲突的构造函数声明。让我们从为什么当前的构造函数不起作用开始。模板函数(构造函数也是)由其签名标识。该签名包括模板参数是什么(类型、非类型、模板)、它们的顺序,以及函数参数和返回类型(构造函数没有返回类型,但这与我们试图实现的目标无关)。所以你要做的是,两次声明同一个constructor!在考虑定义之前,您有一个重复的声明,这当然是不允许的
那么我们能做什么呢?我们可以向每个构造函数添加参数。如果它能区分它们,它们就可以共存。但共存是不够的,我们希望以不同的方式对待它们。我们希望为从T派生的类选择第一个模板化的c'tor,为从SomeClass
派生的类选择第二个模板化的c'tor。我们能做到吗?是的,我们可以。如果我们使我们将添加的模板参数取决于我们的条件,并且在不满足条件时替换失败,那么将从考虑中删除该重载。那太棒了
因此,将所有这些付诸实践:
template <typename E, std::enable_if_t<!std::is_same<SomeClass,T>::value &&
std::is_convertible<E*, T*>::value>* = nullptr>
Wrapper(const E & val)
{
}
template <typename E, std::enable_if_t<std::is_convertible<E*, SomeClass*>::value>* = nullptr>
Wrapper(const E & val)
{
}
template::value>*=nullptr>
包装器(常数E&val)
{
}
模板
包装器(常数E&val)
{
}
那么,上面所说的是什么呢?它添加了另一个带有默认参数的模板参数。它是有条件地这样做的,如果在替换过程中不满足条件,则“坏”的c'tor的签名是错误的。在过载解决方案中不会考虑这一点
我还冒昧地改变了你的状况。您可能只希望接受公开派生自
T
和SomeClass
的类。通过std::is_convertible
可以更好地表达这一点<代码>标准::is_base_of也将允许私有和不明确的多重继承。我还确保在T
是SomeClass
的情况下,我们不会再得到两个冲突的构造函数声明。没有帮助吗?但是如果您使用包装器
?选择哪个实现?为什么不直接编写包装器(constsomeclass&val)
?您在E中使用的哪些信息不在某个类中?我想捕获所传递参数的确切类型。因此,如果我直接使用SomeClass,它的派生类将被视为SomeClass,但是我想使用正确的派生类。。。因为在后续的实现中,我需要的是确切的类型,而不仅仅是基…这是没有帮助的,但是如果您使用包装器
?将选择哪个实现?为什么不选择