如何在 (*this) 上检查 std::is_base_of<>
how to check std::is_base_of<> on (*this)
对于某些任务,没有宏我没能成功。现在我想至少添加一些防止滥用的保护。
我想 static_assert
使用 MYMACRO()
- 在 Base class 的子 class 中,...
- ...即在
run()
方法中
天真的方法失败了:
static_assert(std::is_base_of<Base, typeid(*this)>::value, "Use MYMACRO() only in subclass of Base.");
// =============
// SubOne would work, but not typeid(*this)
//
static_assert(__func__ == "run", "Use MYMACRO() only in run() method.");
// ========
// not a constexpr?
//
重现:
#ifndef __GNUG__
#error "Needs GCC C++"
#endif
#define MYMACRO() \
{\
do { \
/*> > > want static_assert'ions here < < <*/\
/*here comes stuff I coudn't put into an [inline] function,*/ \
/*because it contains GCC Labels-as-Values and */ \
/*conditional return;*/ \
} while(false);\
}
class Base {
public:
virtual int run() = 0;
};
class SubOne : Base {
public:
int run() override {
// ...
MYMACRO();
// ...
};
};
class SubTwo : Base {
public:
int run() override {
// ...
MYMACRO();
// ...
};
};
int main(void)
{
SubOne sub1;
SubTwo sub2;
//a little embedded app
while (true) {
sub1.run();
sub2.run();
}
}
预计可能的问题:
它是做什么用的? - http://dunkels.com/adam/dunkels06protothreads.pdf
作为值的标签:- https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
为什么不 "proper" RTOS with context switching? - I expect the above solution to simplify unit testing under native architecture, side-stepping the need for native (POSIX) port or QEMU/renode or target board。 (不是全部,而是很多测试)
typeid
在这里是错误的工具,因为它 returns 是对 type_info
实例的引用,它不是 *this
的类型,但只包含关于类型。
您可以使用 decltype
:
#include <iostream>
#include <type_traits>
struct base {};
struct foo : base {
foo() {
static_assert(std::is_base_of<base,std::remove_reference<decltype(*this)>::type>::value);
}
};
struct foo_fail {
foo_fail() {
static_assert(std::is_base_of<base,std::remove_reference<decltype(*this)>::type>::value);
}
};
编译器输出:
prog.cc: In constructor 'foo_fail::foo_fail()':
prog.cc:15:23: error: static assertion failed
static_assert(std::is_base_of<base,std::remove_reference<decltype(*this)>::type>::value);
^~~
将typeid(*this)
替换为std::decay_t<decltype(*this)>
。
并且,要在编译时比较字符串,请使用 std::string_view
:
static_assert(std::string_view(__func__) == "main", "Use MYMACRO() only in run() method.");
对于某些任务,没有宏我没能成功。现在我想至少添加一些防止滥用的保护。
我想 static_assert
使用 MYMACRO()
- 在 Base class 的子 class 中,...
- ...即在
run()
方法中
天真的方法失败了:
static_assert(std::is_base_of<Base, typeid(*this)>::value, "Use MYMACRO() only in subclass of Base.");
// =============
// SubOne would work, but not typeid(*this)
//
static_assert(__func__ == "run", "Use MYMACRO() only in run() method.");
// ========
// not a constexpr?
//
重现:
#ifndef __GNUG__
#error "Needs GCC C++"
#endif
#define MYMACRO() \
{\
do { \
/*> > > want static_assert'ions here < < <*/\
/*here comes stuff I coudn't put into an [inline] function,*/ \
/*because it contains GCC Labels-as-Values and */ \
/*conditional return;*/ \
} while(false);\
}
class Base {
public:
virtual int run() = 0;
};
class SubOne : Base {
public:
int run() override {
// ...
MYMACRO();
// ...
};
};
class SubTwo : Base {
public:
int run() override {
// ...
MYMACRO();
// ...
};
};
int main(void)
{
SubOne sub1;
SubTwo sub2;
//a little embedded app
while (true) {
sub1.run();
sub2.run();
}
}
预计可能的问题:
它是做什么用的? - http://dunkels.com/adam/dunkels06protothreads.pdf
作为值的标签:- https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
为什么不 "proper" RTOS with context switching? - I expect the above solution to simplify unit testing under native architecture, side-stepping the need for native (POSIX) port or QEMU/renode or target board。 (不是全部,而是很多测试)
typeid
在这里是错误的工具,因为它 returns 是对 type_info
实例的引用,它不是 *this
的类型,但只包含关于类型。
您可以使用 decltype
:
#include <iostream>
#include <type_traits>
struct base {};
struct foo : base {
foo() {
static_assert(std::is_base_of<base,std::remove_reference<decltype(*this)>::type>::value);
}
};
struct foo_fail {
foo_fail() {
static_assert(std::is_base_of<base,std::remove_reference<decltype(*this)>::type>::value);
}
};
编译器输出:
prog.cc: In constructor 'foo_fail::foo_fail()':
prog.cc:15:23: error: static assertion failed
static_assert(std::is_base_of<base,std::remove_reference<decltype(*this)>::type>::value);
^~~
将typeid(*this)
替换为std::decay_t<decltype(*this)>
。
并且,要在编译时比较字符串,请使用 std::string_view
:
static_assert(std::string_view(__func__) == "main", "Use MYMACRO() only in run() method.");