Jump to content

    

Как в C (C++) написать красиво проверку, что несколько переменных равны?

Так, как понимаете, не работает.

static_assert(g00 == g01 == g02, "Oh!");

Можно

static_assert(g00 == g01 && g01 == g02, "Oh!");

А еще как? А то их 16 штук, этих gXX... надоест сравнивать.

Edited by ViKo

Share this post


Link to post
Share on other sites

ну раз плюсы, то конечно завернуть в макросы :)

 

#define VA_ARGS_NUM_PRIV(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, Pn, ...) Pn
#define VA_ARGS_NUM(...) VA_ARGS_NUM_PRIV(-1, ##__VA_ARGS__, 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
#define COUNT(...) VA_ARGS_NUM(__VA_ARGS__)
 
#define ASSERT(COND,MSG) typedef char static_assert_##MSG[(COND)?1:-1]
 
#define ASSERT_EQ3(A,B,MSG) ASSERT(A==B,MSG)
#define ASSERT_EQ4(A,B,C,MSG) ASSERT(A==B&&B==C,MSG)
#define ASSERT_EQ5(A,B,C,D,MSG) ASSERT(A==B&&B==C&&C==D,MSG)
#define ASSERT_EQ6(A,B,C,D,E,MSG) ASSERT(A==B&&B==C&&C==D&&D==E,MSG)
 
#define CONCAT2(a,b) a##b
#define CONCAT(a,b) CONCAT2(a,b)
#define ASSERT_EQ(...) CONCAT(ASSERT_EQ,COUNT(__VA_ARGS__))(__VA_ARGS__)
 
int main(){
  ASSERT_EQ(1,1,1,1,1,ogh!); //ok
  ASSERT_EQ(1,1,4,1,ugh!); //assert
  return 0;
}


 

 

Edited by _pv

Share this post


Link to post
Share on other sites

В C++, может, готовое есть? equ...? 

Share this post


Link to post
Share on other sites

Первый аргумент static_assert вроде-как должен быть выражением из целочисленных констант времени компиляции. А у вас в заголовке темы вопрос про ПЕРЕМЕННЫЕ, которые на этапе компиляции ещё неизвестны - на то они и переменные. Уточните, что именно хотите проверять на равенство: константы времени компиляции или переменные. Если второе, то static_assert не подходит.

Share this post


Link to post
Share on other sites
18 часов назад, ViKo сказал:

А еще как? А то их 16 штук, этих gXX... надоест сравнивать.

Так пойдёт?

template <typename T, typename... Types>
constexpr auto firstArg(T arg, Types... )
{
    return arg;
}

template <typename T, typename... Types>
constexpr auto isEqual(T arg, Types... args)
{
    if constexpr (sizeof...(args) > 1)
        return (isEqual(args...));
    if constexpr (sizeof...(args) > 0)
        return (arg == firstArg(args...));
    return true;
}

int main()
{
    static constexpr int a1 = 1;
    static constexpr int a2 = 1;
    static constexpr int a3 = 1;
    static_assert(isEqual(a1, a2, a3), "vars are not equal!");
}

ЗЫ. Вот здесь можно потыкать.

Edited by AHTOXA
Исправил код

Share this post


Link to post
Share on other sites

Да, константы, известные при компиляции.

Однако, напрямую сравнить проще будет. 

Share this post


Link to post
Share on other sites

Вообще, если константы должны быть равны, то это одна константа. Или константы, определяемые одна через другую.

Share this post


Link to post
Share on other sites

Это я принадлежность выводов к одному порту GPIO так проверяю. Пытаюсь сделать шаблонный класс порта из отдельных выводов. 

Share this post


Link to post
Share on other sites
19 hours ago, ViKo said:

А еще как? А то их 16 штук, этих gXX... надоест сравнивать.

 

Было когда-то понятие "сигнатурный анализ".

Можно вычислить такую сигнатуру, просто сложив по "модулю два" все константы, и сравнивать их с подобной сигнатурой, но уже входных переменных. Если сравнение сигнатур имеется, то, для убедительности, можно проверить и по-подробней. Если нет, то и сравнения нет. Это как бы увеличивает скорость. Здесь возможны вариации. 

 

Еще один способ сравнения. Попарно вычитать из каждой константы соответствующую переменную, а разности накапливать операцией ИЛИ. Если итоговая накопленная сумма ИЛИ равна нулю, то имеется сравнение по всему ряду. 

Edited by Serhiy_UA

Share this post


Link to post
Share on other sites
2 часа назад, Serhiy_UA сказал:

Можно вычислить такую сигнатуру, просто сложив по "модулю два" все константы, и сравнивать их с подобной сигнатурой, но уже входных переменных. Если сравнение сигнатур имеется, то, для убедительности, можно проверить и по-подробней.

Я прикидывал на эту тему, но просто не получается. Если пара констант отличается одинаково от остальных, то исключающее ИЛИ всех констант будет нулевым. Надо именно со сдвигами делать, как в псевдослучайной последовательности. Опять же, проще сравнить все константы с одной.

Share this post


Link to post
Share on other sites

Какая вам разница, насколько оптимально будет выполнено сравнение? Оно же не в рантайме.
 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now