2

Although I've been coding C++ for many years, I'm relatively new to the standard library (and many other modern C++ features). Going through my code and implementing std::vector (especially for use in parallelisation), I came across an error I really don't understand. Code below is a MCRE (I'm actually using nested loops for processing a bitmap):

#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;
}

The output order is jumbled up, but that's down to parallelisation. What confuses me is why I can't use size_t(h) in the vecH constructor!

Of course, I can just use the static_cast version but, maybe, there is something subtle here I don't understand, which may jump up and bit me on the behind if I don't get to grips with it.

With MSVC (VS-2019, 32- or 64-bit build), I get the following error messages when I use the commented-out line:

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:         ]

EDIT: Can't (yet?) post my own answer, but I should've run the code through 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'
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • 9
    Most vexing parse : `vector vecH(size_t(h));` is a function named `vecH` taking a parameter `h` of type `size_t` and returing a `vector`. – Quentin Aug 26 '19 at 14:40
  • How does `(h)` become a parameter called `h`? – Sam Varshavchik Aug 26 '19 at 14:41
  • 1
    @Quentin That's amazing! And helpful. But - how, on God's Green Earth, was I supposed to search for "Most Vexing Parse?" Hehe! – Adrian Mole Aug 26 '19 at 14:50
  • 1
    @SamVarshavchik `vector vecH(size_t(h));` is interpreted as `vector vecH(size_t h);` – Ted Lyngmo Aug 26 '19 at 14:54
  • So, maybe just good/bad luck so far, but the ***only*** place where such a f-style cast to `size_t` generates an error (or even a warning) is when used in a `std::vector` constructor. (In 1000s of line of code!) – Adrian Mole Aug 26 '19 at 14:55
  • Good ole `C` being daft, maybe? Two simple fixes: use `vecH((size_t(h)))` (sensible) or use `vecH(size_t(h + 0))` (old-style, or daft). – Adrian Mole Aug 26 '19 at 15:00
  • @Adrian or `(size_t)h` instead of `size_t(h)` – acraig5075 Aug 26 '19 at 15:04
  • 1
    "In case of ambiguity between a variable declaration using the direct-initialization syntax (with round parentheses) and a function declaration, the compiler always chooses function declaration. This disambiguation rule is sometimes counter-intuitive and has been called the most vexing parse" https://en.cppreference.com/w/cpp/language/direct_initialization – ThomasMcLeod Aug 26 '19 at 15:05
  • @acraig5075 - But one of the things I'm trying to adopt is not to use C-style casts! Apparently, they're evil. – Adrian Mole Aug 26 '19 at 15:06
  • 1
    Yes, so use `static_cast(h)`. – Ted Lyngmo Aug 26 '19 at 15:18
  • @ThomasMcLeod - Good to know that it ain't just me getting confused! – Adrian Mole Aug 26 '19 at 16:00
  • Tsk, tsk, you shouldn't be using C-style casts *anyway*. – Cody Gray - on strike Jun 17 '20 at 00:02

0 Answers0