如何基于单个用户定义的文字自动添加文字定义

How to automatically add literal definitions, based on a single user-defined literal?

本文关键字:文字 定义 添加 何基于 用户 单个      更新时间:2023-10-16

C++11提供用户定义的文字。我刚刚开始玩他们,这让我想知道是否有可能自动将所有SI乘数添加到我定义的单个文字?

例如,如果我定义

Length operator "" _m(long double m) {
    return Length(m); // Length in meters
}

其中Length是一些Units基类的子类,我希望有一种机制来自动添加(与升压运算符相同的精神)SI乘法器,用于返回Length的所有文字:

// these are added automatically when defining the literal "_m": 
                                         // Length in:
Length operator "" _Ym(long double Ym);  // Yottameters
Length operator "" _Zm(long double Zm);  // Zetameters
...                                      // ...
...                                      // ...
Length operator "" _km(long double km);  // kilometers
Length operator "" _mm(long double mm);  // millimeters
...                                      // ...       
...                                      // ...
Length operator "" _zm(long double zm);  // zeptometers
Length operator "" _ym(long double ym);  // yoctometers

据我所见,除了一些宏的魔力之外,没有办法自动做到这一点,因为所有用户定义的文字都需要一个显式的定义。

. .还是我忽略了什么?

我认为没有"奇怪的宏"就没有办法做到你所要求的。这是我所能得到的:

template<typename T, T (*op)(long double)>
struct SI
{
    // ...
    constexpr static T micro = op (.000001);
    constexpr static T milli = op (.001);
    constexpr static T kilo = op (1000);
    constexpr static T mega = op (1000000);
    // ...
};
struct Length
{
    constexpr Length(long double d) : _d(d) { }
    constexpr operator long double() { return _d; }
    long double _d;
};
constexpr Length operator "" _m(long double m) {
    return Length(m);
}
typedef SI<Length, ::operator "" _m> SI_Length;
int main()
{
    constexpr Length l = 3 * SI_Length::kilo;
    static_assert(l == 3000, "error");
}

如果允许使用奇怪的宏,那么应该使用下面的宏:

#define DEFINE_SI_MULTIPLIERS(T, unit) 
    constexpr T operator "" _u ## unit(long double m) 
    { return ::operator "" _ ## unit(0.000001 * m); } 
    constexpr T operator "" _m ## unit(long double m) 
    { return ::operator "" _ ## unit(0.001 * m); } 
    constexpr T operator "" _k ## unit(long double m) 
    { return ::operator "" _ ## unit(1000 * m); } 
    // ...
DEFINE_SI_MULTIPLIERS(Length, m)
int main()
{
    constexpr Length l = 3.0_km;
    static_assert(l == 3000, "error");
}

只要您愿意自己解析浮点数,就不能使用operator "" _m(const char *)样式吗?这样就可以通过调用一个通用的si感知解析器来为浮点值编写1234k_m