g++ против порядка передачи аргументов intel/clang?

Рассмотрим следующий код (LWS):

#include <iostream>
#include <chrono>

inline void test(
   const std::chrono::high_resolution_clock::time_point& first, 
   const std::chrono::high_resolution_clock::time_point& second)
{
   std::cout << first.time_since_epoch().count() << std::endl;
   std::cout << second.time_since_epoch().count() << std::endl;
}

int main(int argc, char* argv[])
{
   test(std::chrono::high_resolution_clock::now(), 
        std::chrono::high_resolution_clock::now());
   return 0;
}

Вы должны запустить его несколько раз, потому что иногда нет видимой разницы. Но когда есть видимая разница между временем оценки first и second, результат в g++ следующий:

1363376239363175
1363376239363174

и следующее под Intel и Clang :

1363376267971435
1363376267971436

Это означает, что в g++ сначала оценивается аргумент second, а в intel и clang сначала оценивается аргумент first.

Какой из них соответствует стандарту C++11?


person Vincent    schedule 15.03.2013    source источник
comment
Аккуратный способ найти порядок оценки.   -  person GManNickG    schedule 16.03.2013


Ответы (2)


Какой из них соответствует стандарту C++11?

Оба допустимы. Чтобы процитировать стандарт (§8.3.6):

Порядок вычисления аргументов функции не определен.

person NPE    schedule 15.03.2013
comment
Ага. На самом деле, это кусало меня несколько раз в моей карьере. Неоднозначность оценки аргументов функции может привести к ЧРЕЗВЫЧАЙНО тонким проблемам. (Я помню один раз, когда эта ошибка существовала годами, и я не мог найти основную причину, и единственным обходным путем, который я мог найти, было ОТКЛЮЧЕНИЕ ОПТИМИЗАЦИИ ДЛЯ ЭТОГО CPP. Ой.) - person StilesCrisis; 15.03.2013
comment
Кроме того, порядок может зависеть от используемых флагов оптимизации и остального кода. - person Daniel Frey; 15.03.2013
comment
@StilesCrisis Да, и даже если вы знаете о неопределенном порядке оценки аргументов, вы должны помнить, что объект, для которого вызывается метод, также является просто еще одним аргументом. Однажды это случилось со мной, потому что я подумал, что ж, чтобы вызвать метод через ->, он должен сначала оценить левую часть, прежде чем даже начать смотреть на аргументы метода, не так ли?. - person Christian Rau; 16.03.2013

У меня есть немного более простой пример, иллюстрирующий ту же проблему.

bash$ cat test.cpp
#include <iostream>
using namespace std;
int x = 0;
int foo() 
{
    cout << "foo" << endl;
    return x++;
}
int bar()
{
    cout << "bar" << endl;
    return x++;
}
void test_it(int a, int b)
{
    cout << "a = " << a << endl
        << "b = " << b << endl;

}
int main(int argc, const char *argv[])
{
    test_it(foo(),bar()); 
    return 0;
}

bash$ clang++ test.cpp && ./a.out
foo
bar
a = 0
b = 1
bash$ g++ test.cpp && ./a.out
bar
foo
a = 1
b = 0
person wcy    schedule 16.11.2013