C++ 未替换作用域解析运算符后的模板参数
我正在尝试生成一个通用代码,如果B不是D的祖先,它将导致编译错误。我想到的是:C++ 未替换作用域解析运算符后的模板参数,c++,templates,scope-resolution,C++,Templates,Scope Resolution,我正在尝试生成一个通用代码,如果B不是D的祖先,它将导致编译错误。我想到的是: template<typename B, typename D> struct assert_base_of { enum {value = sizeof(B::D)}; } 看起来模板参数D不能代替A1。有人能解释并建议一个解决方案吗?继承没有将派生类包含在基类的作用域中,因此使用作用域解析操作符没有任何意义。正确的替代方法(也适用于多重继承)是滥用重载解析规则: #include <i
template<typename B, typename D>
struct assert_base_of {
enum {value = sizeof(B::D)};
}
看起来模板参数D不能代替A1。有人能解释并建议一个解决方案吗?继承没有将派生类包含在基类的作用域中,因此使用作用域解析操作符没有任何意义。正确的替代方法(也适用于多重继承)是滥用重载解析规则:
#include <iostream>
#include <type_traits>
template<typename Base, typename Derived,
bool = std::is_same<Base, Derived>::value>
struct is_base_of_impl
{
typedef typename std::remove_cv<Base>::type no_cv_base;
typedef typename std::remove_cv<Derived>::type no_cv_derived;
template<typename _Up>
static std::true_type test(no_cv_derived&, _Up);
static std::false_type test(no_cv_base&, int);
//Black Magic
struct converter
{
operator no_cv_derived&();
operator no_cv_base&() const;
};
static const bool value = decltype(test(converter(), 0))::value;
};
template<typename Base, typename Derived>
struct is_base_of_impl<Base, Derived, true>
{
static const bool value = std::is_same<Base, Derived>::value;
};
template<typename Base, typename Derived>
struct is_base_of
: public std::integral_constant<bool,
is_base_of_impl<Base, Derived>::value>
{ };
struct A {};
struct B1 : A {};
struct B2 : A {};
struct C : B1, B2 {};
int main()
{
std::cout << is_base_of<A, B1>::value << "\n";
std::cout << is_base_of<B1, C>::value << "\n";
std::cout << is_base_of<A, C>::value << "\n";
return 0;
}
#包括
#包括
模板
struct是\u impl的\u base\u
{
typedef typename std::remove_cv::type no_cv_base;
typedef typename std::remove_cv::type no_cv_派生;
模板
静态标准:正确的型式试验(无派生的和,向上);
静态标准:错误的型式试验(无cv基础和int);
//黑魔法
结构转换器
{
运算符no_cv_派生();
运算符no_cv_base&()const;
};
静态常量bool value=decltype(test(converter(),0))::值;
};
模板
struct是\u impl的\u base\u
{
静态常量布尔值=std::is_same::value;
};
模板
结构是的基础
:公共标准::积分常数
{ };
结构A{};
结构B1:A{};
结构B2:A{};
结构C:B1,B2{};
int main()
{
std::coutstatic\u assert(std::is\u base\u of::value,“B必须是D的基”)
?我不允许使用std::is\u base\u of,即使我可以,我仍然想知道为什么D不会被替换:)B::D
被解释为成员(不是类型)因为B
在这里是依赖的。无论如何,你不能得到这样一个基类——你需要从D
到B
投射一个指针,以检查D
是否继承B
。请参阅@Veritas答案,了解如何实现的is\u base\u of
B
依赖意味着它依赖于一个模板参数(这里是一个模板参数)。当您编写B::foo
时,如果B
是依赖的,则foo
始终被解释为B
成员的名称(这是因为编译器会查看您的模板两次,并且在第一次运行时不知道B
最终会是什么)。如果要foo
命名类型,则必须使用typename B::foo
。如果要foo
命名模板,则必须使用template B::foo
。此外,您在非模板sizeof(a::B)
案例中观察到的是B
的注入类名称(typenameB
被“注入”到B
,而A
继承了它--A::A
也作为一个类型存在)这是C++中的一个暗角,因为它的行为与模板不同。参见和相关的问题。这里重要的是<代码>:::b>代码>命名一个类型,而不是一个成员。我可能是错的,但是在测试之后,我认为您的解决方案对于多重继承不起作用。如果从B1和B2继承,则两者都是错误的。从C继承(非虚拟继承),当我做is_base_of::value时,我得到0。@pyx:You can dois_base_of::value&&is_base_of::value
。我想这应该更恰当地称为is_direct_base of
。@Veritas:欢迎来到1k rep!@AlexandreC。我刚刚编辑了答案,这也是libstdc++内部使用的。
main.cpp:16:22: error: ‘D’ is not a member of ‘A2’
#include <iostream>
#include <type_traits>
template<typename Base, typename Derived,
bool = std::is_same<Base, Derived>::value>
struct is_base_of_impl
{
typedef typename std::remove_cv<Base>::type no_cv_base;
typedef typename std::remove_cv<Derived>::type no_cv_derived;
template<typename _Up>
static std::true_type test(no_cv_derived&, _Up);
static std::false_type test(no_cv_base&, int);
//Black Magic
struct converter
{
operator no_cv_derived&();
operator no_cv_base&() const;
};
static const bool value = decltype(test(converter(), 0))::value;
};
template<typename Base, typename Derived>
struct is_base_of_impl<Base, Derived, true>
{
static const bool value = std::is_same<Base, Derived>::value;
};
template<typename Base, typename Derived>
struct is_base_of
: public std::integral_constant<bool,
is_base_of_impl<Base, Derived>::value>
{ };
struct A {};
struct B1 : A {};
struct B2 : A {};
struct C : B1, B2 {};
int main()
{
std::cout << is_base_of<A, B1>::value << "\n";
std::cout << is_base_of<B1, C>::value << "\n";
std::cout << is_base_of<A, C>::value << "\n";
return 0;
}