【发布时间】:2018-06-21 12:22:43
【问题描述】:
我对以下我在is_base_of 上启用了专业化的情况感到有些困惑。
is_base_of 需要正在检查的类型的完整定义才可用。但是,正在被特化的类型被用作正在检查的基类型的成员 - 所以两者都需要在另一个之前定义,我无法转发声明继承关系。
令人困惑的是,如果我改为标记基础并启用此标记,它就可以工作。当然,要使其工作,此时必须知道继承关系。那么,如果没有完整的定义,为什么is_base_of 不能工作呢?
#define OPTION 2 // OPTION 2 : broken, OPTION 1 : works
#include <iostream>
#include <type_traits>
using namespace std;
template <typename T,typename Enable=void>
struct child;
template <typename T>
struct base
{
typedef T type;
#if OPTION ==1
struct base_tag{};
#endif
};
#if OPTION ==2
template <typename T>
struct child < T, typename std::enable_if < std::is_base_of< base<typename T::type>, T>::value>::type>
{
const char* value = "specialization";
};
#else
template <typename T>
struct child < T, std::void_t<typename T::base_tag> >
{
const char* value = "specialization";
};
#endif
template <typename T>
struct dervived : base<T>
{
child<dervived> child_;
typedef T type;
};
int main() {
std::cout << dervived<int>().child_.value << std::endl;
return 0;
}
【问题讨论】:
-
你应该把你的例子一分为二,因为它已经很难理解并且必须通读条件块并没有真正的帮助。
-
我倾向于同意霍尔特的观点。如果您只保留选项 2,它将更具可读性。标签解决方法真的无关紧要。
-
您可以将选项 2 缩减为:godbolt.org/g/Ncm6Ad,将选项 1 缩减为大致相同的长度。
slimbody在这里不相关,您只想检查是否为fatbody选择了专业化。 -
但问题是关于标签解决方法 - 所以并非无关紧要。标签变通方法要求被检查的类型是从提供标签的基础继承的。那么这不需要知道继承关系,因此为什么 is_base_of 在使用之前需要完整的定义。但是当继承并使用标签时,不会。
-
@AndyG:我认为这与
void_t与enable_if_t无关,但is_base_of和T::tag之间的类型支持不完整。
标签: c++