C++ CRTP-从基类检查派生类是否满足要求

C++ CRTP-从基类检查派生类是否满足要求,c++,c++14,crtp,C++,C++14,Crtp,奇怪的重复模板模式可以用来实现一种静态多态性。例如: #include <iostream> template< class Derived > struct Base { static void print ( ) { std::cout << Derived::number_to_print << '\n'; } }; struct Derived final : Base<

奇怪的重复模板模式可以用来实现一种静态多态性。例如:

#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();
}
这不起作用,因为在实例化
Base
时,
Derived
只被前向声明过,即它是不完整的,除了它是一个结构这一事实之外,还不知道它是什么

我一直在挠头,因为我认为这些检查可能对基类的用户有帮助,但还没有找到任何方法来做到这一点


有可能吗?如果有,怎么做?

作为一个肮脏的把戏,您可以将静态断言移动到成员函数的主体中。由于成员函数定义有效地出现在类定义之后,因此
派生的类型在成员函数体内是完整的

请注意,类模板的成员函数本身就是函数模板,因此它们只有在使用时才被实例化(或者如果类模板被显式实例化)。

因为您可以将静态断言移动到成员函数体中

当您以非
静态成员函数的形式提供功能时,您可以让断言函数体成为构造函数体,而不是当前的静态成员函数

例如

#包括
#包括
使用名称空间std;

#定义STATIC_ASSERT(e)STATIC_ASSERT(e,#e”//作为替代方法(其他答案确实很好),您可以使用私有方法并依赖sfinae:

#包括
#包括
模板
结构基{
静态空白打印(){
打印();
}
私人:
模板
静止的
std::如果启用,则启用
打印(){

std::cout好的,重点是添加检查,这些检查在早期捕获错误并发出明确的诊断,因此只有在实例化方法时才会进行检查这一事实是一个障碍,而不是一个好处(对于静态方法,这个问题似乎是不可避免的;只有使用构造函数的@Cheers方法才能解决它)。此外,您的方法似乎没有提供任何明确的诊断;问题将隐藏在大量的编译器错误中。理想情况下,即使没有使用任何方法,也会执行检查。如果这不可能,而且必须在成员函数内部进行检查,我能想到的最好方法是将它们放在私有静态
constexpr
fun中从每个成员函数调用Action,以避免重复它们。虽然不优雅,但非常有用。
#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();
}
#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();
}
#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();
}