What's “<?=” operator in C++? [duplicate]

2020-03-01 03:14发布

I came across the following code here, which is from the C++ implementation of Dijkstra algorithm using an adjacency matrix.

//read in edges keeping only the minimum
for(int i=0; i<E; i++) {
    int v1,v2,tmp;
    fin >> v1; fin >> v2;
    fin >> tmp;
    adjmat[v1][v2]<?=tmp; // <?= sets left to min(left,right)
    adjmat[v2][v1]<?=tmp;
}

Pay attention to the last two lines, which apply operator <?=. As being commented, the following line

adjmat[v1][v2]<?=tmp; // <?= sets left to min(left,right)

will set left to min(left,right).

I never see this operator before. I tried the code in VS, it can not compile. What is it? How can it set left to be min(left,right)?

2条回答
一夜七次
2楼-- · 2020-03-01 03:53

It is equivalent to:

adjmat[v1][v2] = (adjmat[v1][v2]<tmp)? adjmat[v1][v2] : tmp;

In general:

a OP ?= b; <=> a = (a OP b)? a : b;

A little example (compiled using MingW2.95 and C-Free IDE on Windows) showing what @Kerrek SB said: the GCC extension evalute operands only once, which it's nice

#include <stdio.h>

int f(int x)
{
    printf ("Calling f() with x=%d\n", x);
    return x*x;
}

int main()
{
    int a,b,c;

    printf ("A and B? ");
    scanf ("%d%d", &a, &b);

    c = a;
    a = (a<f(b))? a : f(b);
    printf ("A using ternary operator: %d\n", a);

    a = c;
    a <?= f(b);
    printf ("A using weird GCC extension: %d\n", a);

    return 0;
}


A and B? 3 1
Calling f() with x=1
Calling f() with x=1
A using ternary operator: 1
Calling f() with x=1
A using weird GCC extension: 1
查看更多
Explosion°爆炸
3楼-- · 2020-03-01 03:55

It is an old GCC extension; it does what it says in the comment (it's the compound assignment form of the "minimum" operator). This is not standard C++.

The difference between a = a < b ? a : b and a <?= b is that the latter only evaluates each operand once.


In modern standard C++, I believe you could write an "assign the minimum" algorithm like this:

auto && __a = a;
auto && __b = b;
if (!(__a < __b)) { __a = std::forward<decltype(__b)>(__b); }

This should be the body of a macro which has the effect of a <?= b, and a and b are arbitrary expressions, potentially with side effects. Or you could wrap it into a template:

template <typename T,
          typename U,
          typename P = std::less<std::common_type_t<std::decay_t<T>, std::decay_t<U>>>
T && clamp_to_minimum(T && a, U && b, P p = P())
{
    if (!(p(a, b))) { a = std::forward<U>(b); }
    return std::forward<T>(a);
}
查看更多
登录 后发表回答