В чем разница между static_cast‹size_t›(i) и size_t(i) в конструкторе std::vector?

Хотя я много лет программировал на C++, я относительно новичок в стандартной библиотеке (и во многих других современных функциях C++). Просматривая свой код и реализуя std::vector (особенно для использования в параллелизации), я наткнулся на ошибку, которую действительно не понимаю. Ниже приведен код MCRE (на самом деле я использую вложенные циклы для обработки растрового изображения):

#include <vector>
#include <numeric>
#include <algorithm>
#include <execution>
#include <iostream>

using namespace std;

int main()
{
    int32_t h = 12;
    cout << "First loop:" << endl;
    vector<unsigned int> vecH(static_cast<size_t>(h)); iota(begin(vecH), end(vecH), 0);
//  vector<unsigned int> vecH(size_t(h)); iota(begin(vecH), end(vecH), 0);  // Gives error!
    for_each(execution::par, begin(vecH), end(vecH), [&](int py) {
        cout << py << " ";
    });
    cout << "." << endl;
    return 1;
}

Порядок вывода перепутан, но это связано с распараллеливанием. Меня смущает, почему я не могу использовать size_t(h) в конструкторе vecH!

Конечно, я могу просто использовать static_cast версию, но, возможно, здесь есть что-то тонкое, чего я не понимаю, что может подскочить и укусить меня сзади, если я не возьму себя в руки с этим.

С MSVC (VS-2019, 32- или 64-разрядная сборка) я получаю следующие сообщения об ошибках, когда использую закомментированную строку:

StackFlow.cpp(14,48): error C2672:  'begin': no matching overloaded function found
StackFlow.cpp(14,58): error C2893:  Failed to specialize function template 'unknown-type std::begin(_Container &)'
StackFlow.cpp(14,58): message :  With the following template arguments:
StackFlow.cpp(14,58): message :  '_Container=std::vector<unsigned int,std::allocator<_Ty>> (size_t)'
StackFlow.cpp(14,58): error C2784:  'const _Elem *std::begin(std::initializer_list<_Elem>) noexcept': could not deduce template argument for 'std::initializer_list<_Elem>' from 'std::vector<unsigned int,std::allocator<_Ty>> (size_t)'
StackFlow.cpp(14,58): error C2784:         with
StackFlow.cpp(14,58): error C2784:         [
StackFlow.cpp(14,58): error C2784:             _Ty=unsigned int
StackFlow.cpp(14,58): error C2784:         ]

РЕДАКТИРОВАТЬ: Не могу (пока?) опубликовать свой собственный ответ, но я должен был запустить код через clang-cl:

StackFlow.cpp(14,30): warning :  parentheses were disambiguated as a function declaration [-Wvexing-parse]
StackFlow.cpp(14,31): message :  add a pair of parentheses to declare a variable
StackFlow.cpp(14,48): error :  no matching function for call to 'begin'

person Adrian Mole    schedule 26.08.2019    source источник
comment
Самый неприятный анализ: vector<unsigned int> vecH(size_t(h)); — это функция с именем vecH, принимающая параметр h типа size_t и возвращающая vector<unsigned int>.   -  person Quentin    schedule 26.08.2019
comment
Как (h) становится параметром с именем h?   -  person Sam Varshavchik    schedule 26.08.2019
comment
@Квентин Это потрясающе! И полезно. Но — как же мне на Божьей Зеленой Земле искать Самый Досадный Парс? Хе-хе!   -  person Adrian Mole    schedule 26.08.2019
comment
@SamVarshavchik vector<unsigned int> vecH(size_t(h)); интерпретируется как vector<unsigned int> vecH(size_t h);   -  person Ted Lyngmo    schedule 26.08.2019
comment
Так что, может быть, пока просто повезло/не повезло, но единственное место, где такое приведение в стиле f к size_t генерирует ошибку (или даже предупреждение), — это когда используется в конструкторе std::vector. (В тысячах строк кода!)   -  person Adrian Mole    schedule 26.08.2019
comment
Может быть, старый добрый C спятил? Два простых исправления: используйте vecH((size_t(h))) (разумно) или используйте vecH(size_t(h + 0)) (старый стиль или глупость).   -  person Adrian Mole    schedule 26.08.2019
comment
@ Адриан или (size_t)h вместо size_t(h)   -  person acraig5075    schedule 26.08.2019
comment
В случае неоднозначности между объявлением переменной с использованием синтаксиса прямой инициализации (с круглыми скобками) и объявлением функции компилятор всегда выбирает объявление функции. Это правило устранения неоднозначности иногда противоречит здравому смыслу и было названо самым неприятным синтаксическим анализом en.cppreference. com/w/cpp/language/direct_initialization   -  person ThomasMcLeod    schedule 26.08.2019
comment
@ acraig5075 - Но одна из вещей, которую я пытаюсь внедрить, это не использовать приведения в стиле C! Судя по всему, они злые.   -  person Adrian Mole    schedule 26.08.2019
comment
Да, так что используйте static_cast<size_t>(h).   -  person Ted Lyngmo    schedule 26.08.2019
comment
@ThomasMcLeod - Приятно знать, что не только я запутался!   -  person Adrian Mole    schedule 26.08.2019
comment
Тск, тск, вы не должны использовать приведения в стиле C в любом случае.   -  person Cody Gray    schedule 17.06.2020