考虑以下示例:
#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;
}如何解决这个问题( Base类未知的Derived类型定义)?
编辑:我发现了一个非常简单的技巧。谁能给我解释一下为什么下面的版本是有效的,而之前的版本不起作用?这个技巧是适用于标准的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;
}发布于 2012-12-24 22:25:09
您必须使用在定义Base之前声明的包装类(这里是value_getter)。然后,可以在定义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:
};它不是很漂亮,但至少它可以工作。
发布于 2012-12-24 23:08:59
您的技巧之所以有效,是因为在完成类派生之后,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;
}但是,您的实际代码可能还有其他需求,这使得这一点不切实际。
https://stackoverflow.com/questions/14022493
复制相似问题