2016-07-24 38 views
1

我想在不改变其作用域的情况下为类启用静态成员。 考虑下面的抽象例如:在不改变成员范围的情况下有条件地启用静态成员

template<uint R, uint C> 
class Foo 
{ 
    static Foo ID; 

    /* other members */ 
}; 

现在我想用静态成员,如:

Foo<3, 3> foo = Foo<3, 3>::ID; 

的问题是,ID场只能存在R == C时。
Foo实际上是一个MatrixID其身份其中仅存在对于方阵)

所以,我有当所述条件满足时有条件地使静态ID构件。我目前的解决办法是这样的:

struct EmptyBase { }; 

template<uint R, uint C> 
class _Foo_Square 
{ 
    static Foo<R, C> ID; 
}; 

template<uint R, uint C> 
class Foo : public std::conditional<R == C, _Foo_Square<R, C>, EmptyBase>::type 
{ 
    /* other members */ 
}; 

但现在我不能写Foo<3, 3>::ID访问它。我必须写_Foo_Square<3, 3>::ID

不幸的是,我的应用程序的设计强迫它可以通过Foo类作用域访问。 如果不是条件成员,我可以在Foo类中编写using _Foo_Square<3, 3>::ID;

有没有解决这个问题的方法?

+0

子类似乎是个好主意。 – erip

+2

“*但是现在我不能写'Foo <3, 3> :: ID'来访问它,我必须写'_Foo_Square <3, 3> :: ID'。*”要从哪里访问它?正如你所示,唯一的“问题”是“ID”是私人的...... – ildjarn

+1

是的,你的代码在你公开的情况下工作:http://coliru.stacked-crooked.com/a/0ceb5c6660a0fd8b –

回答

1

答案是要么修复你的代码的一些错误,和/或切换到更好的编译器。

加入适当forward声明,宣称静态类成员作为public后,下面没有问题,编译用gcc 6.1.1:

#include <utility> 

struct EmptyBase { }; 

template<int R, int C> class Foo; 

template<int R, int C> 
class _Foo_Square 
{ 
public: 

    static Foo<R, C> ID; 
}; 

template<int R, int C> 
class Foo : public std::conditional<R == C, _Foo_Square<R, C>, EmptyBase>::type 
{ 
    /* other members */ 
}; 

void foobar() 
{ 
    Foo<3, 3> a=Foo<3, 3>::ID; 
} 
+0

事情是,我一如既往地忘记把'public:'放在这里的细分版本中。我已经在我的代码中得到它,但仍然无法使用我的gcc 6.1.1进行编译。它只是说*没有在此范围内声明* – bricklore

+0

适用于我。显示的代码与海湾合作委员会编译6.1.1 –

+0

是的,我开始相信,我的代码中有其他的东西,防止这种情况。其实我有两层继承,但我不认为这是问题。 – bricklore

0

专业基类Bar,你可以这样做

#include <iostream> 

template <std::size_t, std::size_t> 
struct Foo; 

template <std::size_t, std::size_t> 
struct Bar 
{ }; 

template <std::size_t N> 
struct Bar<N, N> 
{ static Foo<N, N> ID; }; 

template <std::size_t R, std::size_t C> 
struct Foo : Bar<R, C> 
{ 
    // other members 
}; 

int main() 
{ 
    Foo<3, 3> foo = Foo<3, 3>::ID; 

    return 0; 
} 
0

最简单的版本,我能想到的:

typedef unsigned int uint; 

template<uint R, uint C> 
class Foo 
{ 
    //no ID here 
}; 

template<uint R> 
class Foo<R,R> 
{ 
public: 
    static constexpr Foo ID = Foo(); 
}; 

int main() 
{ 
    Foo<3,3> foo1 = Foo<3,3>::ID; //ok 

    Foo<3,4> foo2 = Foo<3,4>::ID; //error 
}