Пользовательские литералы, которые отличаются только возвращаемыми значениями - PullRequest
1 голос
/ 24 апреля 2020

Это то, чего я хочу добиться: у меня есть два пользовательских литерала, один из которых принимает длинное двойное значение и возвращает наклон, а другой также принимает длинное двойное значение и возвращает влажность. Теперь я хочу использовать оба UDL в одной области. К сожалению, в обоих случаях единицей измерения является «процент».

struct slope
{
    long double val;
};
slope operator ""_perc(long double v)
{
    slope s = {v};
    return s;
}

struct humidity
{
    long double val;
};
humidity operator ""_perc(long double v)
{
    humidity h = {v};
    return h;
}

void func(void)
{
    slope s(0.0_perc);
    humidity h(0.0_perc);
}

Это невозможно, поскольку сигнатуры двух функций не могут различаться только в типе возвращаемого значения. Мы могли бы использовать пространства имен:

namespace slp
{
    slope operator ""_perc(long double v)
    {
        slope s = {v};
        return s;
    }
}
namespace hum
{
    humidity operator ""_perc(long double v)
    {
        humidity h = {v};
        return h;
    }
}

, но я позволю себе констатировать, что пользовательские литералы имеют смысл только при использовании «неквалифицированного». Мы не хотим использовать их следующим образом:

void func(void)
{
    slope s(slp::operator"" _perc(0.0));
    humidity h(hum::operator"" _perc(0.0));
}

Поскольку оба UDL должны использоваться в одной и той же области, мы не можем использовать 'using' из-за неоднозначности, которую он создает:

using namespace slp;
using namespace hum;

или

using slp::operator ""_perc;
using hum::operator ""_perc;

Так что я застрял. Есть ли какой-нибудь - желательно элегантный - способ добиться того, чего я хочу?

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

Одно очевидное решение состоит в том, чтобы придумать разные имена.

Если вы предпочитаете сохранять «процент» как количество, вы можете использовать класс процентов и определять конструкторы для каждого комментария :

struct Percent {
    long double value;
    explicit constexpr Percent(long double v)
        : value{v}
    {
    }
};

constexpr Percent operator""_perc(long double v) noexcept
{
    return Percent(v);
}

struct slope {
    long double val;
    explicit slope(Percent pc)
        : val{pc.value}
    {
    }
};

// humidity similar

Вы можете определить explicit операторов преобразования, если вам нужно, чтобы slope и humidity были агрегатами.

0 голосов
/ 24 апреля 2020

Вы можете обманывать, создавая дополнительную область (как сразу же выполняется лямбда):

void func(void)
{
    auto s = [](){ using namespace slp; return 0.0_perc; }(); // slope
    auto h = [](){ using namespace hum; return 0.0_perc; }(); // humidity
    // ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...