shr*_*ike 5 c++ templates sfinae c++11 c++14
我有一组使用成员typedef链接的类,Next
如下所示:
class Y; class Z;
class X { public: typedef Y Next; };
class Y { public: typedef Z Next; };
class Z { };
Run Code Online (Sandbox Code Playgroud)
我需要一种方法来获得链的最终类,从链的任何类开始.感谢这篇文章的接受答案,我写了以下代码:
// cond_type<Condition, Then, Else>::type // selects type 'Then' if 'Condition' is true, or type 'Else' otherwise
template <bool Condition, typename Then, typename Else = void>
struct cond_type
{
typedef Then type;
};
template <typename Then, typename Else>
struct cond_type<false, Then, Else >
{
typedef Else type;
};
template <class C, typename _ = void>
struct chain
{
typedef C last;
};
template <class C>
struct chain<C, typename cond_type<false, typename C::Next>::type>
{
typedef typename chain<typename C::Next>::last last;
};
Run Code Online (Sandbox Code Playgroud)
使用上面的模板chain<C>::last
,以下代码正确地实例化了3个类的对象Z
,如预期的那样:
chain<X>::last z1;
chain<Y>::last z2;
chain<Z>::last z3;
Run Code Online (Sandbox Code Playgroud)
但是,如果所考虑的类集形成继承层次结构,则采用以下方式:
class U; class V;
class T { public: typedef U Next; };
class U : public T { public: typedef V Next; };
class V : public U { };
Run Code Online (Sandbox Code Playgroud)
然后,使用模板chain<C>::last
,使用C
上述任何类的集合,例如:
chain<T>::last v;
Run Code Online (Sandbox Code Playgroud)
导致以下编译错误:
1>test.cpp(88): error C3646: 'last' : unknown override specifier
Run Code Online (Sandbox Code Playgroud)
我理解问题是类V
继承自typedef V Next
父类中的定义U
,导致模板的专用形式的编译,chain<V,V>
而应该使用通用类而不是V
没有成员Next
.
无论如何,我被困在这里,因为我需要一种有效的机制,即使在这种类层次结构的情况下也是如此.
我怎么能这样做?
PS:类之间的继承必须保持公开; 成员typedef必须保持公开.
它很简单:
template <typename T, typename = void> struct last_t_impl
{
using type = T;
};
template <typename T> struct last_t_impl
<T, std::enable_if_t<!std::is_same_v<typename T::Next, T>>>
{
using type = typename last_t_impl<typename T::Next>::type;
};
template <typename T> using last_t = typename last_t_impl<T>::type;
Run Code Online (Sandbox Code Playgroud)
用法:
last_t<T> v1;
last_t<U> v2;
last_t<V> v3;
Run Code Online (Sandbox Code Playgroud)
如果您需要上面的代码来编译C++ 14(而不是C++ 17),请更改std::is_same_v<A,B>
为std::is_same<A,B>::value
.
请注意,您typename cond_type<false, T>::type
可以替换为std::void_t<T>
(或std::conditional_t<false,T,void>
在C++ 14中).但在这种情况下,它不是必需的,因为链的末端将被SFINAE检测到std::is_same_v<typename T::Next, T>
.(即使T::Next
由于某种原因不存在,SFINAE仍然会启动并且last_t<T>
将会是公正的T
.)
归档时间: |
|
查看次数: |
370 次 |
最近记录: |