Pattern-match/SFINAE 关于特定 类 的容器参数化?
Pattern-match/SFINAE on parameterization of container for specific classes?
我有 Base
class 和一些 Derived
class。来自外部代码的某些位模式可以制作这些,并且有构建它们的通用代码。该通用代码必须使用显式模板 "factory":
auto d = factory<D>(data); // where D is some Derived class
此工厂为 class 派生自 Base 的 ES 启用了 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;
}
我想添加另一个适用于 std::experimental::optional<Derived>
的变体,用于位模式指示未设置的情况。在这种情况下,通用代码将传入以下任一类型:
auto dod = factory<DOD>(data); // DOD can be Derived or std::optional<Derived>
使用这样的显式参数化,我将如何创建另一个 SFINAE 变体,它 "pattern match" 只存在于 std::experimental::optional<any class whose base is Base>
?
如果我能写的话,我的愿望是:
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;
}
是否有实现愿望的非虚构版本?我查看了 "using SFINAE for template class specialisation"(和其他几个),似乎有一些方法可以合作破解一些东西,如果我写的话,用一个容器来完成它(?),但我是否错过了一个简单的答案?
#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;
}
我有 Base
class 和一些 Derived
class。来自外部代码的某些位模式可以制作这些,并且有构建它们的通用代码。该通用代码必须使用显式模板 "factory":
auto d = factory<D>(data); // where D is some Derived class
此工厂为 class 派生自 Base 的 ES 启用了 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;
}
我想添加另一个适用于 std::experimental::optional<Derived>
的变体,用于位模式指示未设置的情况。在这种情况下,通用代码将传入以下任一类型:
auto dod = factory<DOD>(data); // DOD can be Derived or std::optional<Derived>
使用这样的显式参数化,我将如何创建另一个 SFINAE 变体,它 "pattern match" 只存在于 std::experimental::optional<any class whose base is Base>
?
如果我能写的话,我的愿望是:
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;
}
是否有实现愿望的非虚构版本?我查看了 "using SFINAE for template class specialisation"(和其他几个),似乎有一些方法可以合作破解一些东西,如果我写的话,用一个容器来完成它(?),但我是否错过了一个简单的答案?
#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;
}