删除括号的c ++宏

c++ macro that removes parentheses

假设我的 .cpp 代码中某处有这样的东西

name(min,max)

我可以写一个宏吗?

#define GET_NAME(A) //transforms name(min,max) -> name;

还有宏?

#define GET_RANGE(A) // transforms name(min,max) -> std::pair<T,N>(min,max);

用法应该是这样的

GET_NAME(r(0,255)) -> r
GET_RANGE(r(0,255)) -> std::pair<int,int>(0,255)

真正的目标是提供这样的东西

#ifndef PIXEL_PIXEL_HPP
#define PIXEL_PIXEL_HPP

#include <ostream>
#include <array>

template<typename T, unsigned int N>
union Pixel;

#define DECLARE_PIXEL(NAME, T, N, ...)                                                  \
template<>                                                                              \
union Pixel<T,N> {                                                                      \
    static const int SIZE = N;\
    T args[N];                                                                          \
    struct{                                                                                 \
        T __VA_ARGS__;\
    };\
                                                                          \
    Pixel() = default;                                                                  \
    Pixel(std::initializer_list<T> l) { std::move(l.begin(),l.end(),args); };            \
    Pixel(const Pixel<T,N>& other) = default;                                           \
    Pixel(Pixel<T,N>&& other) = default;                                                \
    T operator[](unsigned int i) const{                                                 \
        return args[i];\
    }                                                                                   \
    T& operator[](unsigned int i) {                                                     \
        return args[i];\
    }\
    bool operator==(const Pixel<T,N>& rhs) const{                                           \
        for(int i = 0; i < N; ++i) {                                                     \
            if(args[i] != rhs[i]) {                                               \
                return false;                                                           \
            }                                                                           \
        }                                                                               \
        return true;                                                                    \
    };                                                                                  \
    bool operator!=(const Pixel<T,N>& rhs) const{                                           \
        return !(*this == rhs);                                                       \
    };                                                                                   \
    bool operator<(const Pixel<T,N>& rhs) const{                                            \
        for(int i = 0; i < N; ++i) {                                                     \
            if(args[i] >= rhs[i]) {                                                     \
                return false;\
            }\
        }                                                                               \
        return true;\
    };                                                                                  \
    bool operator>(const Pixel<T,N>& rhs) const{                                            \
        for(int i = 0; i < N; ++i) {                                                    \
            if(args[i] <= rhs[i]) {                                                \
                return false;\
            }\
        }                                                                               \
        return true;\
    };                                                                                 \
    bool operator<=(const Pixel<T,N>& rhs) const{                                           \
        return !(*this > rhs);\
    };                                                                                  \
    bool operator>=(const Pixel<T,N>& rhs) const{                                           \
        return !(*this < rhs);\
    };                                                                                  \
    Pixel<T,N>& operator=(const Pixel<T,N>& rhs) = default;                             \
    Pixel<T,N>& operator=(Pixel<T,N>&& rhs) = default;                                  \
    Pixel<T,N> operator*(T scalar) const{                                                 \
        Pixel<T,N> result;                                                              \
        for(int i = 0; i < N; ++i) {                                                    \
            result[i] = static_cast<T>(args[i] * scalar); \
        }                                                                               \
        return result;\
    };                                                                                  \
    friend Pixel<T,N> operator*(T scalar, const Pixel<T,N>& rhs){                    \
        return rhs * scalar;\
    }\
    Pixel<T,N> operator*(const Pixel<T,N>& other) const {                                     \
        Pixel<T,N> result;\
        for(int i = 0; i < N; ++i) {                                                    \
            result[i] = static_cast<T>(args[i] * other[i]);\
        }                                                                               \
        return result;\
    };\
    Pixel<T,N> operator/(T scalar) const {                                          \
        return (*this) * (1/scalar);\
    };                                                                                  \
    friend Pixel<T,N> operator/(T scalar, const Pixel<T,N>& pixel) {                                          \
        return pixel / scalar;\
    }\
    Pixel<T,N> operator/(const Pixel<T,N>& other) const {                               \
        Pixel<T,N> result;                                                              \
        for(int i = 0; i < N; ++i) {                                                    \
            result[i] = static_cast<T>(args[i] / other[i]);\
        }                                                                               \
        return result;\
    };\
    Pixel<T,N> operator+(const Pixel<T,N>& rhs) const {                                       \
        Pixel<T,N> result;                                                              \
        for(int i = 0; i < N; ++i) {                                                    \
            result[i] = static_cast<T>(args[i] + rhs[i]); \
        }                                                                               \
        return result;\
    };                                                                                  \
    Pixel<T,N> operator-(const Pixel<T,N>& rhs) const {                                 \
        Pixel<T,N> result;                                                              \
        for(int i = 0; i < N; ++i) {                                                    \
            result[i] = static_cast<T>(args[i] - rhs[i]);\
        }                                                                               \
        return result;                                                                  \
    }                                                                                   \
    Pixel<T,N>& operator +=(const Pixel<T,N>& rhs)  {                              \
        *this = *this + rhs;                                                            \
        return *this;\
    }                                                                                   \
    Pixel<T,N>& operator -=(const Pixel<T,N>& rhs) {                                    \
        *this = *this - rhs;                                                            \
        return *this;\
    }                                                                                   \
    Pixel<T,N>& operator *=(const Pixel<T,N>& rhs) {                                     \
        *this = *this * rhs;                                                            \
        return *this;\
    }                                                                                   \
    Pixel<T,N>& operator /=(const Pixel<T,N>& rhs) {                                    \
        *this = *this / rhs;                                                            \
        return *this;\
    }\
    friend std::ostream& operator<<(std::ostream& os, const Pixel<T,N>& pixel) {        \
        for(const auto& elem : pixel.args){                                                   \
            os<<elem << " ";                                                     \
        }                                                                               \
        return os;\
    }                                                                                   \
    \
};                                                                                      \
using NAME = Pixel<T,N>;                                                                \


DECLARE_PIXEL(RGB, int, 3,r(0,255), g(0,255), b(0,255))

DECLARE_PIXEL(ARGB, float, 4, a(0,1), r(0,1), g(0,1), b(0,1))

#undef DECLARE_PIXEL

#endif //PIXEL_PIXEL_HPP

并且还会有一些新的像素类型,例如 HSL。 请注意,变量的范围部分将存储为成对的静态向量,而变量的名称将存储在结构中。

不,宏不能做到这一点。如果您愿意稍微更改语法,例如,将 r(0,255) 写成 (r)((0,255))(r,(0,255)) 那么这是可行的。例如,参见 Boost Preprocessor library 文档。

您将无法直接编写 T __VA_ARGS__;,您需要迭代参数(Boost 预处理器也可以这样做)。

话虽如此,无论问题是什么,宏几乎都不是一个好的答案。

注意:这个答案被接受后我重写了它以使其更简单。

我建议不要为此使用单个宏或 union,而是向数组中的特定元素添加访问器。

您可以在 Pixel class 模板中实现基本成员函数,并继承 rgbargb classes 保存数组和实现访问器。

示例:

#include <array>
#include <iostream>

template<typename T>
struct Pixel : public T {
    static constexpr size_t SIZE = sizeof(T);

    // only methods here, no non-static member variables

    // iterators
    auto cbegin() const { return this->arr.cbegin(); }
    auto cend() const { return this->arr.cend(); }
    auto begin() const { return cbegin(); }
    auto end() const { return cend(); }
    auto begin() { return this->arr.begin(); }
    auto end() { return this->arr.end(); }

    // an example of a function adding one Pixel to another
    Pixel& operator+=(const Pixel& rhs) {
        auto rit = rhs.begin();
        for(auto& v : this->arr) v += *rit++;
        return *this;
    }
};

// make the functions returning a new object into free functions
template<typename T>
Pixel<T> operator+(const Pixel<T>& a, const Pixel<T>& b) {
    Pixel rv = a;
    rv += b;
    return rv;
}

// streaming the values in a Pixel<T>
template<typename T>
std::ostream& operator<<(std::ostream& os, const Pixel<T>& p) {
    os << '{';
    auto it = p.cbegin();
    if constexpr(sizeof(*it) == 1) os << static_cast<int>(*it);
    else os << *it;

    for(++it; it != p.cend(); ++it) {
        os << ',';
        if constexpr(sizeof(*it) == 1) os << static_cast<int>(*it);
        else os << *it;        
    }
    return os << '}';
}

然后用访问器定义rgbargb

struct rgb {
    std::uint8_t& r() { return arr[0]; }
    std::uint8_t& g() { return arr[1]; }
    std::uint8_t& b() { return arr[2]; }

    std::uint8_t r() const { return arr[0]; }
    std::uint8_t g() const { return arr[1]; }
    std::uint8_t b() const { return arr[2]; }

    std::array<std::uint8_t, 3> arr;  
};

struct argb {
    float& a() { return arr[0]; }
    float& r() { return arr[1]; }
    float& g() { return arr[2]; }
    float& b() { return arr[3]; }

    float a() const { return arr[0]; }
    float r() const { return arr[1]; }
    float g() const { return arr[2]; }
    float b() const { return arr[3]; }

    std::array<float, 4> arr;  
};

用法示例:

int main() {
    Pixel<rgb> x {{126,127,128}};
    Pixel<rgb> y {{129,128,127}};
    Pixel<rgb> z = x + y;

    Pixel<argb> foo {{1.1f, 2.2f, 3.3f, 4.4f}};
    Pixel<argb> bar {{1.1f, 2.2f, 3.3f, 4.4f}};

    foo += bar;

    std::cout << z << '\n';
    std::cout << foo << '\n';
    std::cout << sizeof(z) << '\n';
}

可能的输出:

{255,255,255}
{2.2,4.4,6.6,8.8}
3