有没有一种通用方法来"unprotect"静态常量成员?
Is there a generic way to "unprotect" static const members?
有时我面临一个具有受保护静态成员的类(无法修改(的情况,例如
struct foo {
protected:
static const int x = 42;
static const int y = 101;
static const int z = 404;
// ... and more ...
};
不幸的是,我需要访问这些成员,不是在派生类中,而是在其他代码中。我写了这个:
struct bar : foo {
static const int x = foo::x;
static const int y = foo::y;
static const int z = foo::z;
};
但感觉相当笨拙。从长远来看,应该修改类foo
以提供对这些常量的访问,但只要不是这种情况,我就希望有更好的东西。我可以沿着以下行编写一个宏
int x = SOME_MACRO_VOODOO(foo,x);
不过,我想知道是否有办法避免宏。我尝试了很多方法,例如这个
struct f {
protected:
static const int x = 42;
};
template <typename T, int T::*P>
struct bar : f {
int get_value() { return this->*P;}
};
int main() {
bar<f,&f::x>().get_value();
}
失败,因为&f::x
不是指向成员的指针,而只是一个int *
,当然f::x
不可访问:
prog.cc: In function 'int main()':
prog.cc:12:16: error: could not convert template argument '& f::x' from 'const int*' to 'int f::*'
bar<f,&f::x>().get_value();
^
prog.cc:12:5: error: 'const int f::x' is protected within this context
bar<f,&f::x>().get_value();
^~~~~~~~~~~~
prog.cc:3:22: note: declared protected here
static const int x = 42;
听起来你正在寻找一个使用声明。可以在类定义的上下文中使用using
将成员从基类导入派生类。如果using
与要导入的成员之一具有不同的访问规范,则可以在派生类的上下文中有效地"更改"该成员的访问规范。
struct foo {
protected:
static const int x = 42;
static const int y = 101;
static const int z = 404;
// ... and more ...
};
struct bar : foo {
using foo::x;
using foo::y;
using foo::z;
};
int main()
{
// Should work fine
int a = bar::x;
}
#define BYPASS_STATIC_PROTECTED( CLASS, FIELD )
[]()->decltype(auto){ struct cheater:CLASS { using CLASS::FIELD; }; return cheater::FIELD; }()
auto x= BYPASS_STATIC_PROTECTED( foo, x );
我们也可以在成员字段上执行此操作:
template<class T>
struct tag_t { using type=T; };
#define BYPASS_MEMPTR_PROTECTED_HELPER( FIELD )
[](auto tag){ using T=typename decltype(tag)::type; struct cheater:T { using T::FIELD; }; return &cheater::FIELD; }
#define BYPASS_MEMPTR_PROTECTED( CLASS, FIELD )
BYPASS_MEMPTR_PROTECTED_HELPER(FIELD)(tag_t<CLASS>{})
#define BYPASS_PROTECTED_ON_MEMBER( FIELD )
[](auto& obj )->decltype(auto) {
using T = std::decay_t<decltype(obj)>;
return obj.* BYPASS_MEMPTR_PROTECTED_HELPER( FIELD )(tag_t<T>{});
}
以及类似的成员函数:
#define BYPASS_PROTECTED_ON_METHOD( MEMBER )
[](auto& obj, auto&&...args )->decltype(auto) {
using T = std::decay_t<decltype(obj)>;
return (obj.* BYPASS_MEMPTR_PROTECTED_HELPER( MEMBER )(tag_t<T>{}))( decltype(args)(args)... );
}
活生生的例子。
测试代码:
struct foo {
protected:
static const int x = 42;
static const int y = 101;
static const int z = 404;
// ... and more ...
int member = 7;
int method(int v) const { return -v; }
};
std::cout << BYPASS_STATIC_PROTECTED( foo, x ) << "n";
std::cout << BYPASS_PROTECTED_ON_MEMBER( member )( f ) << "n";
std::cout << BYPASS_PROTECTED_ON_METHOD( method )( f, 1 ) << "n";
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- #为""定义宏;静态";针对不同的上下文
- cmake如何在fedora工作站中找到boost静态库包
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 将公共但非静态的成员函数与ALGLIB集成
- cmake在我的项目中所需的所有静态库都不成功
- C++从另一个类访问公共静态向量的正确方法是什么
- 基于boost的程序的静态链接——zlib问题
- 在静态库中嵌入类方法
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 如何在C++中获得"静态纯虚拟"功能?
- 私有类型的静态常量成员
- 使用gcc从静态链接的文件中查找可选符号
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 如何在C++中使用非静态成员函数作为回调函数
- 将静态库链接到不带-fPIC的共享库中
- 静态结构和一个定义规则
- 为什么虚函数不能是静态的和全局的?
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 有没有一种通用方法来"unprotect"静态常量成员?