Mixing typedef and CRTP?
Mixing typedef and CRTP?
考虑以下示例:
#include <iostream>
#include <iostream>
#include <type_traits>
template<typename Type, template<typename> class Crtp>
class Base
{
public:
typedef int value;
// f1: OK
// Expected result: casts 4.2 to Base<Type, Crtp>::value
value f1() {return 4.2;}
// f2: NOT OK
// Expected result: casts 4.2 to Crtp<Type>::value
// But f2 does not compile: no type named 'value'
// in 'class Derived<double>'
typename Crtp<Type>::value f2() {return 4.2;}
};
template<typename Type>
class Derived : public Base<Type, Derived>
{
public:
typedef Type value;
};
int main()
{
Derived<double> a;
std::cout<<a.f1()<<std::endl;
std::cout<<a.f2()<<std::endl;
return 0;
}
如何解决此问题(Derived
Typedef在Base
类中未知)?
编辑:我找到了一个非常简单的技巧。有人可以向我解释为什么以下是有效的,并且以前的版本不起作用?标准C 11的技巧是否可以,还是由于编译器的工作方式(在此G 4.7.1)?
是有效的#include <iostream>
#include <iostream>
#include <type_traits>
template<typename Type, template<typename> class Crtp>
class Base
{
public:
typedef int value;
value f1() {return 4.2;}
template<typename T = Crtp<Type>> typename T::value f2() {return 4.2;}
};
template<typename Type>
class Derived : public Base<Type, Derived>
{
public:
typedef Type value;
};
int main()
{
Derived<double> a;
std::cout<<a.f1()<<std::endl;
std::cout<<a.f2()<<std::endl;
return 0;
}
您必须使用包装类别(在这里是value_getter
),该类别在定义Base
之前被声明。然后,您可以在定义Derived
之前立即对其进行专业化:
template<typename T>
struct value_getter;
template<typename Type, template<typename> class Crtp>
class Base
{
public:
typedef int value;
value f1() {return 4.2;}
// in 'class Derived<double>'
typename value_getter<Crtp<Type> >::value f2() {return 4.2;}
};
template<typename Type>
class Derived;
template<typename Type>
struct value_getter<Derived<Type> > {
typedef Type value;
};
template<typename Type>
class Derived : public Base<Type, Derived>, public value_getter<Derived<Type> >
{
public:
};
它并不完全漂亮,但至少可以起作用。
您的技巧有效,因为F2现在才能实例化,直到实际使用,当类派生完成后。
在您的特定示例中,我可能只建议这样做:
#include <iostream>
#include <iostream>
#include <type_traits>
template<typename Type, template<typename> class Crtp>
class Base
{
public:
typedef int value;
value f1() {return 4.2;}
Type f2() {return 4.2;}
};
template<typename Type>
class Derived : public Base<Type, Derived>
{
public:
typedef Type value;
};
int main()
{
Derived<double> a;
std::cout<<a.f1()<<std::endl;
std::cout<<a.f2()<<std::endl;
return 0;
}
但是您的真实代码可能具有使这不切实际的其他需求。
相关文章:
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 为什么 Clang 不允许"and"作为函数名称?
- 位阵列上的快速AND运算
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- 尝试使用继承和模板实现CRTP.Visual Studio正在生成编译器错误
- CRTP 单一实例不完整类型或非文本类型
- BoostPython and CMake
- OpenSSL BIO and SSL_read
- Gurobi GRBModel and GRBmodel in C++
- CRTP 中的复制赋值运算符 - gcc vs clang 和 msvc
- 将具有固定签名的自定义函数名称注入 CRTP
- 如何在MISRA C++之后实施CRTP
- 检测使用 CRTP 的类中的成员函数
- 简化使用 CRTP 模式的类的声明
- C++ CRTP initialization
- std::visit and std::variant usage
- 概念可以与 CRTP 习语一起使用吗?
- Mixing typedef and CRTP?
- Inheritance and CRTP