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变体,它将“模式匹配”只存在于forstd::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@Reritoextract\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;
}