sig*_*igy 7 c++ static-assert crtp type-traits c++11
我想确保派生类实现一个特定的静态方法.我认为这样做应该可以使用static_assert,std :: is_same,decltype,CRTP并且可能使用SFINAE.但是,到目前为止,我发现的类似代码非常复杂,似乎我还没有完全理解它使我无法将其用于我的需求.
到目前为止我尝试过的是这个
template <class T>
class Base
{
static_assert(std::is_same<decltype(T::foo(1)), int>::value, "ERROR STRING");
};
class Derived : public Base <Derived>
{
public:
static int foo(int i) { return 42; };
};
Run Code Online (Sandbox Code Playgroud)
但是,它没有编译告诉我,即使方法正确实现,Derived也没有名为foo的元素.此外,在static_assert内的表达式中为foo提供实际参数会感觉不对.
搜索SO揭示了一个类似的问题,最终引导我到这段代码,检查一个类型有方法begin()和end()返回迭代器.所以我试着采用这个代码来满足我的需求.
template <class T>
class Base
{
template<typename C>
static char(&g(typename std::enable_if<std::is_same<decltype(static_cast<int(C::*)(int)>(&C::foo)), int(C::*)(int)>::value, void>::type*))[1];
template<typename C>
static char(&g(...))[2];
static_assert(sizeof(g<T>(0)) == 1, "ERROR STRING");
};
Run Code Online (Sandbox Code Playgroud)
但是这段代码没有编译,因为断言触发了.
所以我的问题是
typename C::const_iterator(C::*)() const
示例代码到底意味着什么?是不是一个const函数返回C :: const_iterator并且没有参数?究竟是什么C::*
意思?那么为什么int(C::*)(int)
我的情况会出错呢?我正在使用MSVC 12,但如果可能,代码应该是可移植的.
Cas*_*sey 12
这是使用CRTP时的一个常见问题:Base<Derived>
在Derived
基数列表中遇到它时被实例化,此时它还Derived
不是一个完整的类型,因为其声明的其余部分尚未被解析.有各种解决方法.因为static_assert
,您需要延迟断言的实例化,直到Derived
完成.一种方法是将断言放在一个Base
你知道必须实例化的成员函数中- 析构函数总是一个很好的选择(在Coliru生活):
template <class T>
class Base
{
public:
~Base() {
static_assert(std::is_same<decltype(T::foo(1)), int>::value, "ERROR STRING");
}
};
class Derived : public Base<Derived>
{
public:
static int foo(int) { return 42; };
};
Run Code Online (Sandbox Code Playgroud)
解决问题#2:C::*
是"指向类成员的指针"的语法C
.所以int(*)(int)
是"函数指针服用单一int
参数并返回int
",并且int(C::*)(int)
是类似于"指针的成员函数C
采用单个int
参数并返回int
".怪物
typename C::const_iterator(C::*)() const
Run Code Online (Sandbox Code Playgroud)
将转换为"指向C
不带参数并返回的常量成员函数的指针C::const_iterator
",当然typename
必须指示依赖名称C::const_iterator
是一个类型.