假设我有一个接受某种类型T
类。这意味着它可以接受一些类型optional<U>
。我想禁用的功能,如果它是一个optional
类型的不是,但如果是...那么我想知道这种类型U
。
我已经能够通过模板禁用此功能,但我不知道如何处理检测模板模板类,而不写两次同一类,使一个模板化的模板版本。
Code:
class Dummy{};
template <typename T>
class C {
T t;
public:
C(T t) : t(std::move(t)) { }
T get() {
return t;
}
// Will clearly fail when T doesn't have a value_type
template <typename R = T, typename OptT = typename T::value_type, typename = std::enable_if_t<std::is_same_v<T, optional<OptT>>>>
std::vector<OptT> stuff() {
std::vector<OptT> vec;
// Do stuff, fill vec
return vec;
}
};
int main() {
C<Dummy> c{Dummy()}; // Error
// C<optional<Dummy>> c{Dummy()}; // Works fine
c.get();
}
在这一过程中,我得到
main.cpp中:在“C类”实例化:
main.cpp中:33:14:从这里需要
main.cpp中:25:23:错误:没有键入 '类假' 命名为 'VALUE_TYPE'
std::vector<OptT> stuff() { ^~~~~
注:这是好的,如果有这个类的一个特例,如果std::optional
我所关心的是检测。我并不需要它的任何其他类型的...只有可选的工作。这可允许某种模板专业化的,但我也没弄清楚如何研究,当它这样做。
我怎样才能让这个功能只有当类型为std::optional
出现,然后当它是那种类型,能够抓住可选的内部类型?我能做到这一点不沾T
的模板定义? (如在,我可以做到这一点,而把它当作template <typename T>
而不改变它template <template <typename> T>
或具有复制此类,其中上述两种制成)
你的问题就在这里:
// Will clearly fail when T doesn't have a value_type
template <typename R = T,
typename OptT = typename T::value_type,
typename = std::enable_if_t<std::is_same_v<T, optional<OptT>>>>
这是你推出一个新的虚拟模板参数,R
,但你还在使用旧的,T
,你所有的检查。所以没有检查实际上是相关的。 SWAP他们R
和你的罚款。
一种不同的方法是推迟到只使用一个标签参数不同的功能:
template <typename> struct tag { };
template <typename R=T>
auto stuff() -> decltype(stuff_impl(tag<R>{})) {
return stuff_impl(tag<R>{});
}
现在在哪里,你可以有效地只使用Normal模板扣拉出类型:
template <typename U>
std::vector<U> stuff_impl(tag<std::optional<U>>) {
return {};
}
我的建议如下定义自定义类型特征
template <typename>
struct optionalType
{ };
template <typename T>
struct optionalType<std::optional<T>>
{ using type = T; };
当且仅当有type
调用定义T
(该std::optional<T>
的类型std::optional
)。
现在你的stuff()
简直成了
template <typename R = T,
typename OptT = typename optionalType<R>::type>
std::vector<OptT> stuff() {
std::vector<OptT> vec;
// Do stuff, fill vec
return vec;
}
观察到OptT
,所述std::optional
的类型,存在仅当R
(又名T
)是std::optional
;你有一个替代的故障,否则,禁止stuff()
。
您可以验证
C<Dummy> c0{Dummy()};
C<std::optional<Dummy>> c1{Dummy()};
//c0.stuff(); // compilation error
c1.stuff(); // compile