Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用C++;模板_C++_Templates_Template Argument Deduction - Fatal编程技术网

C++ 使用C++;模板

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

我有一个包装类。任何T或从T派生的对象都应可转换到此包装器

我还希望“Someclass”的任何对象或从“Someclass”派生的对象都可以转换为包装器。这两种情况下的实施需要分开。我怎样才能做到这一点

以下是我想要的行为:

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,但是我想使用正确的派生类。。。因为在后续的实现中,我需要的是确切的类型,而不仅仅是基…这是没有帮助的,但是如果您使用
包装器
?将选择哪个实现?为什么不选择