在不更改成员范围的情况下有条件地启用静态成员

时间:2016-07-24 12:51:16

标签: c++ class templates c++11 conditional

我想为类启用静态成员而不更改其范围。 请考虑以下抽象示例:

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;

这个问题有解决方法吗?

3 个答案:

答案 0 :(得分:1)

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

在添加适当的前向声明并将静态类成员声明为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;
}

答案 1 :(得分: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;
 }

答案 2 :(得分: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
}