首页 > 解决方案 > 在 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++gccvisual-c++clang

解决方案


虽然 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


推荐阅读