mercredi 30 septembre 2015

Pattern-match/SFINAE on parameterization of container for specific classes?

I have Base class and some Derived classes. Certain bit patterns that come in from external code can make these, and there is generic code which builds them. That generic code has to use an explicit template "factory":

auto d = factory<D>(data); // where D is some Derived class

This factory is SFINAE-enabled for classes that are derived from Base:

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;
}

I'd like to add another variant that works with std::optional<Derived> for the cases when the bit patterns indicate things are unset. In this case the generic code would be passing in either type:

auto dod = factory<DOD>(data); // DOD can be Derived or std::optional<Derived>

Using explicit parameterization like this, how would I create another SFINAE variant which would "pattern match" into existence only for for std::optional<any class whose base is Base>?

The desire would be if I could write:

template<
    std::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;
}

Is there a non-imaginary version of implementing the desire? I looked at "using SFINAE for template class specialisation" (and several others) and it seems like maybe there are some ways to cooperatively hack something together to do it with a container if I wrote it (?), but am I missing an easy answer?

Aucun commentaire:

Enregistrer un commentaire