C++ 特定类容器参数化的模式匹配/SFINAE?

C++ 特定类容器参数化的模式匹配/SFINAE?,c++,templates,c++11,sfinae,C++,Templates,C++11,Sfinae,我有Base类和一些派生类。来自外部代码的某些位模式可以生成这些位模式,并且有构建它们的通用代码。该通用代码必须使用显式模板“factory”: auto d=工厂(数据);//其中D是某个派生类 对于从基派生的类,此工厂已启用SFINAE: template< class T, typename = typename std::enable_if< std::is_base_of<Base, T>::value >::ty

我有
Base
类和一些
派生类。来自外部代码的某些位模式可以生成这些位模式,并且有构建它们的通用代码。该通用代码必须使用显式模板“factory”:

auto d=工厂(数据);//其中D是某个派生类
对于从基派生的类,此工厂已启用SFINAE:

template<
    class T,
    typename = typename std::enable_if<
        std::is_base_of<Base, T>::value
    >::type
>
T factory(ExternalData &data) {
    T result;
    if (!result.initFromData(&data))
        throw std::runtime_error("data is not set");
    return result;
}
模板<
T类,
typename=typename标准::启用\u如果<
std::是::value的基础吗
>::类型
>
T工厂(外部数据和数据){
T结果;
if(!result.initFromData(&data))
throw std::runtime_错误(“未设置数据”);
返回结果;
}
我想添加另一个变体,用于位模式指示未设置的情况。在这种情况下,通用代码将传入以下任一类型:

auto dod = factory<DOD>(data); // DOD can be Derived or std::optional<Derived>
auto-dod=工厂(数据);//国防部可派生或std::可选
使用像这样的显式参数化,我如何创建另一个SFINAE变体,它将“模式匹配”只存在于for
std::experimental::optional(和其他几个)中,并且似乎有一些方法可以合作地将某件事破解到一起,以使用容器来完成,如果我编写了它(?),但我是否错过了一个简单的答案?

#包括
#include <type_traits>

template <typename T>
struct extract_optional;

template <typename T>
struct extract_optional<std::experimental::optional<T>>
{
    using type = T;
};

template <typename T>
using extract_optional_t = typename extract_optional<T>::type;

template <
    typename T,
    typename OP = extract_optional_t<T>,
    typename = typename std::enable_if<
        std::is_base_of<Base, OP>::value
    >::type
>
std::experimental::optional<OP> factory(ExternalData &data) {
    OP result;
    if (!result.initFromData(&data))
        return nullopt;
    return result;
}
模板 结构提取_可选; 模板 结构提取\可选 { 使用类型=T; }; 模板 使用extract\u optional\u t=typename extract\u optional::type; 模板< 类型名T, typename OP=提取\u可选\u t, typename=typename标准::启用\u如果< std::是::value的基础吗 >::类型 > 标准::实验::可选工厂(外部数据和数据){ OP结果; if(!result.initFromData(&data)) 返回nullopt; 返回结果; }

实时解决的问题!:-)非常感谢。它似乎做的把戏,并有很好的意义…我需要测试它多一点,以确保它的工作。关于这类事情,我记得的一件事是,为了防止它们被弄脏,如果有人碰巧为OP提供了一个显式的参数化,那么就使用静态断言。类似这样的T等于std::experimental::optional…@HostileFork,甚至更好。好的。你能再详细一点吗?我对你回答的要点很感兴趣不幸的是,它太简洁了,我无法回答understand@Rerito
extract\u可选
作为模板结构的原型建立。如果在任何地方都没有它的定义,那么你就不能将它用于任何东西,并且在所有试图使用它的情况下都会失败。但是它被专门化为允许与一件事一起使用:
可选的
…因此它只在那里成功实例化。我们得到了两件我们想要的东西:用于检查和使用的OP-contained类型,以及保证T是std::optional(注意,通过内联修复)
template<
    std::experimental::optional<class T>, // imaginary
    typename = typename std::enable_if<
        std::is_base_of<Base, T>::value
    >::type
>
std::optional<T> factory(ExternalData &data) {
    T result;
    if (!result.initFromData(&data))
        return nullopt;
    return result;
}
#include <type_traits>

template <typename T>
struct extract_optional;

template <typename T>
struct extract_optional<std::experimental::optional<T>>
{
    using type = T;
};

template <typename T>
using extract_optional_t = typename extract_optional<T>::type;

template <
    typename T,
    typename OP = extract_optional_t<T>,
    typename = typename std::enable_if<
        std::is_base_of<Base, OP>::value
    >::type
>
std::experimental::optional<OP> factory(ExternalData &data) {
    OP result;
    if (!result.initFromData(&data))
        return nullopt;
    return result;
}