c++ - 在 clang 和 gcc 中是否有 Visual C++ __declspec(属性声明属性)的替代方法?
问题描述
有一个 Microsoft 特定的扩展,可以像这样定义属性 getter 和 setter:
// declspec_property.cpp
struct S {
int i;
void putprop(int j) {
i = j;
}
int getprop() {
return i;
}
__declspec(property(get = getprop, put = putprop)) int the_prop;
};
int main() {
S s;
s.the_prop = 5;
return s.the_prop;
}
有没有办法用 clang 或 gcc 定义属性声明属性?如果我搜索__declspec
,我找到的只是__declspec(dllexport)
,但我不是在寻找那个。
解决方案
虽然 C++ 不提供对智能可覆盖运算符的支持(并且没有 gcc 扩展),但该语言允许您使用其现有功能来实现它。
以下示例(假定未涵盖所有情况!)显示了使用本机 C++ 11 或更高版本的可能解决方案。
我们可以使用虚拟覆盖来覆盖属性,但这不是现代智能属性在其他语言(如 swift、C# 等)中的工作方式,所以相反 - 我使用 lambdas 为 setter 和 getter 注入覆盖代码。
// The following is by no means a FULL solution!
#include <functional>
#include <iostream>
#include <cassert>
template<typename T>
class Property {
public:
Property(){}
operator const T& () const {
// Call override getter if we have it
if (getter) return getter();
return get();
}
const T& operator = (const T& other) {
// Call override setter if we have it
if (setter) return setter(other);
return set(other);
}
bool operator == (const T& other) const {
// Static cast makes sure our getter operator is called, so we could use overrides if those are in place
return static_cast<const T&>(*this) == other;
}
// Use this to always get without overrides, useful for use with overriding implementations
const T& get() const {
return t;
}
// Use this to always set without overrides, useful for use with overriding implementations
const T& set(const T& other) {
return t = other;
}
// Assign getter and setter to these properties
std::function<const T&()> getter;
std::function<const T&(const T&)> setter;
private:
T t;
};
// Basic usage, no override
struct Test {
Property<int> prop;
};
// Override getter and setter
struct TestWithOverride {
TestWithOverride(){
prop.setter = [&](const int& other){
std::cout << "Custom setter called" << std::endl;
return prop.set(other);
};
prop.setter = std::bind(&TestWithOverride::setProp,this,std::placeholders::_1);
prop.getter = std::bind(&TestWithOverride::getProp,this);
}
Property<int> prop;
private:
const int& getProp() const {
std::cout << "Custom getter called" << std::endl;
return prop.get();
}
const int& setProp(const int& other){
std::cout << "Custom setter called" << std::endl;
return prop.set(other);
}
};
int main(int,char**){
Test t;
TestWithOverride t1;
t.prop = 1;
assert(t.prop == 1);
t1.prop = 1;
assert(t1.prop == 1);
/*
Expected output:
1. No aborts on assertions
2. Text:
Custom setter called
Custom getter called
*/
return 0;
}
编译类似:
c++ -std=c++11 test.cpp -o test
运行:
./test
推荐阅读
- oauth - 如何处理我设计的网站上的 disallowed_useragent 错误?
- neo4j - 我的 neo4j 配置是什么?
- javascript - Webhook 似乎不起作用
- dynamic - 动态链接到产品类别
- c# - 在数据网格中显示用户 ID
- javascript - 错误!如何绕过/更改某些语法以缩小流程 - Javascript
- python - 如何通过在一行中给出其值来创建列表?
- javascript - 为什么这个使用 getElementById 的 `even` 函数不起作用?
- python - 在熊猫的列匹配中从另一个数据框中替换 NaN 值的正确方法
- javascript - 如何在 jQuery 的文档就绪函数中使用模块中的(全局)变量?