在不更改成员范围的情况下有条件地启用静态成员
Enabling a static member conditionally without changing the member scope
我想为 class 启用静态成员而不更改其范围。
考虑以下抽象示例:
template<uint R, uint C>
class Foo
{
static Foo ID;
/* other members */
};
现在我想像这样使用静态成员:
Foo<3, 3> foo = Foo<3, 3>::ID;
问题是ID
字段只能在R == C
时存在。
(Foo
实际上是一个 Matrix
和 ID
它的恒等式只存在于方阵中)
所以我必须在满足条件时有条件地启用静态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
class 范围访问。
如果它不是条件成员,我可以在 Foo class.
中写 using _Foo_Square<3, 3>::ID;
这个问题有解决办法吗?
答案是修复代码中的一些错误,and/or切换到更好的编译器。
添加适当的前向声明并将静态 class 成员声明为 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;
}
专门化一个基地 class 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;
}
我能想到的最简单的版本:
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
}
我想为 class 启用静态成员而不更改其范围。 考虑以下抽象示例:
template<uint R, uint C>
class Foo
{
static Foo ID;
/* other members */
};
现在我想像这样使用静态成员:
Foo<3, 3> foo = Foo<3, 3>::ID;
问题是ID
字段只能在R == C
时存在。
(Foo
实际上是一个 Matrix
和 ID
它的恒等式只存在于方阵中)
所以我必须在满足条件时有条件地启用静态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
class 范围访问。
如果它不是条件成员,我可以在 Foo class.
using _Foo_Square<3, 3>::ID;
这个问题有解决办法吗?
答案是修复代码中的一些错误,and/or切换到更好的编译器。
添加适当的前向声明并将静态 class 成员声明为 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;
}
专门化一个基地 class 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;
}
我能想到的最简单的版本:
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
}