CRTP-从基类中检查派生类是否满足要求
CRTP - Checking from the base class that the derived one meets requirements
奇怪的重复模板模式可以用来实现一种静态多态性。例如:
#include <iostream>
template<
class Derived
>
struct Base
{
static void print ( )
{
std::cout << Derived::number_to_print << 'n';
}
};
struct Derived final :
Base<
Derived
>
{
static constexpr unsigned int number_to_print = 27;
};
int main ( )
{
Derived::print();
}
这将按预期操作并打印27
。
现在,我想向基类添加检查,以断言派生类满足某些要求。在上面给出的例子中,这样的检查可以是:
#include <iostream>
#include <type_traits>
template<
class Derived
>
struct Base
{
// --- Checks begin
static_assert( std::is_same<
decltype(Derived::number_to_print),
unsigned int
>::value,
"static member `number_to_print' should be of type `unsigned int'" );
// --- Checks end
static void print ( )
{
std::cout << Derived::number_to_print << 'n';
}
};
struct Derived final :
Base<
Derived
>
{
static constexpr unsigned int number_to_print = 27;
};
int main ( )
{
Derived::print();
}
这不起作用,因为在实例化Base<Derived>
时,Derived
只被正向声明,即它是不完整的,除了它是一个结构之外,什么都不知道。
我一直在挠头,因为我认为这些检查可能对基类的用户有帮助,但还没有找到任何方法。
有可能吗?,如果是,怎么做?
当您将功能提供为非static
成员函数,而不是当前的static
成员函数时,您可以让断言函数体成为构造函数的体。
例如
#include <iostream>
#include <type_traits>
using namespace std;
#define STATIC_ASSERT( e ) static_assert( e, #e " // <- is required" )
template< class A, class B >
constexpr auto is_same_() -> bool { return std::is_same<A, B>::value; }
template< class Derived >
struct Base
{
Base()
{
STATIC_ASSERT((
is_same_< remove_cv_t< decltype( Derived::number_to_print ) >, int >()
));
}
void print() const
{
std::cout << Derived::number_to_print << 'n';
}
};
struct Derived final
: Base< Derived >
{
static constexpr int number_to_print = 27;
};
auto main()
-> int
{
Derived::Base().print();
}
作为一个肮脏的技巧,您可以将静态断言移动到成员函数的主体中。由于成员函数定义有效地出现在类定义之后,Derived
的类型在成员函数体中是完整的。
注意,类模板的成员函数本身就是函数模板,因此只有在使用时(或者如果类模板是显式实例化的),它们才会被实例化。
作为一种替代方法(其他答案确实很好),您可以使用私有方法并依赖sfinae:
#include <iostream>
#include <type_traits>
template<class Derived>
struct Base {
static void print ( ) {
print<Derived>();
}
private:
template<class D>
static
std::enable_if_t<std::is_same<std::remove_cv_t<decltype(D::N)>, unsigned int>::value>
print() {
std::cout << D::N << 'n';
}
};
struct Derived final: Base<Derived> {
static constexpr unsigned int N = 27;
};
int main ( ) {
Derived::print();
}
这样,只有在实际使用print
时才会出现错误。
相关文章:
- 如果仍然不满足要求,如何使 if 语句重复?
- "<"满足严格的弱排序是否意味着不需要"=="定义?
- 存在"等价",以便"comp"满足比较要求
- C++20 是否要求将源代码存储在文件中?
- 是否可以要求虚函数使用C++"覆盖"说明符?
- 在不再满足条件后,while 循环是否停止验证?
- 什么 STL 算法可以确定容器中的一个项目是否满足谓词?
- 提升::不满足 ASIO 读取处理程序类型要求
- 检查变量是否满足没有呼叫的过载功能
- 在运行时询问变体中的替代是否满足某个概念
- if 语句贯穿始终,无论是否满足条件
- g++是否满足std::string C++11的要求
- CRTP-从基类中检查派生类是否满足要求
- 检查是否满足任意不等式的列表
- 浮点数的无限是否满足这些方程
- 可执行文件是否可以要求管理员权限?(Windows 7)
- 在constexpr中使用argc,是否严格要求所涉及的任何子表达式都是常量表达式
- 循环中字符串的输出会根据是否满足某个条件而变化
- C++标准是否强制要求对wchar_t进行编码
- 在C++如何验证是否满足某些条件