Bug when using boost::optional with boost::program_options?

Before I spend too long tracking this down (I'm only seeing it in an Appveyor Windows build, since I do most of my work on Linux), I wanted to see if anyone else has experienced this issue. I'm trying to use boost::program_options to parse a command line arg and store it into a boost::optional, however I get a surprising compilation error[1]. This appears to have been introduced sometime between Boost 1.60 and 1.62 (Appveyor doesn't have Boost 1.61). I see that there were some significant changes to boost::optional between those revisions, so maybe that's the cause? The following test case *might* reproduce the issue, but sadly, rextester only has Boost 1.60, so it works there[2]. If it fails for someone with Boost 1.62+, then great! (Well, not "great", but you know what I mean.) Interestingly, it's not until Boost 1.65[3] that boost::program_options claims to support storing values into boost::optional; it's worked for me since long before that, possibly because I `#include <boost/optional/optional_io.hpp>`. If this isn't enough for others to help confirm this issue, that's ok; I'll try to get a Windows dev environment set up to provide more details in the coming week. I just wanted to send this out before I forgot about it... If it matters, the Appveyor build I'm seeing this with uses Visual Studio 2015 Update 3. Thanks, - Jim [1] https://hastebin.com/awutivawew.txt [2] http://rextester.com/QGBH48883 [3] https://www.boost.org/users/history/version_1_65_0.html

On 2 June 2018 at 07:53, Jim Porter via Boost-users < boost-users@lists.boost.org> wrote:
If it matters, the Appveyor build I'm seeing this with uses Visual Studio 2015 Update 3.
VS2015 has been qualified (quite some time ago already, on reddit) as "buggy" and "to be dropped", because of that, by STL. VS2017 has <optional> and it is ABI-compatible with VS2015. degski -- *"If something cannot go on forever, it will stop" - Herbert Stein*

Regardless of what was written above (or what permeates reddit, etc), most shops are still using VS2015 or lower, so it does matter, actually. The fact is that a lot of places are slow to upgrade toolchains because there's a cost to doing so, regardless of what the vendor recommends. There are still places using VC6, for example, so I'd wager that the vast majority of windows devs are not using VS2017. -- chris

On 5 June 2018 at 15:41, Chris Glover via Boost-users < boost-users@lists.boost.org> wrote:
Regardless of what was written above (or what permeates reddit, etc), most shops are still using VS2015 or lower, so it does matter, actually.
If one doesn't care about bugs in compiler, STL and IDE, and support for later standards, why would one care to upgrade Boost at all? I was quoting Steven T. Lavavej <https://nuwen.net/stl.html> (STL) and Billy O'Neill, who both have leading roles in VC (and its STL) development. The fact you saw it on reddit.com might have something to do with the fact that STL is also one of the moderators of /r/cpp. degski -- *"If something cannot go on forever, it will stop" - Herbert Stein*

Dear Jim, I remember having some troubles using boost::optional with boost::program_options. I fixed it by adding the following lines: namespace boost {// Add custom validator to use boost::program_options on boost::optional<> typestemplate<class T>void validate(boost::any& v, std::vector<std::string> const& values, boost::optional<T>* typeTag, int) { if (!values.empty()) { boost::any a; using namespace boost::program_options; validate(a, values, (T*)0, 0); v = boost::any(boost::optional<T>(boost::any_cast<T>(a))); } } } I don’t remember the details, but I think I took that from more recent version of Boost to be able to use my code with older version of Boost. With that, my code compiles and runs fine - on Linux for Boost from 1.54 to 1.66 with various compilers (GCC 4.8 to 7.3, Intel Compiler, Clang) - on Windows for Boost 1.60 with MSVC++ from 9 (2008) to 14 (2015). I hope this will help. Best regards, Xavier On Tue, Jun 5, 2018 at 5:21 PM degski via Boost-users < boost-users@lists.boost.org> wrote:
-- Dr Xavier BESSERON Research associate FSTC, University of Luxembourg Campus Belval, Office MNO E04 0415-040 Phone: +352 46 66 44 5418 http://luxdem.uni.lu/

On 6/5/2018 8:51 AM, Xavier Besseron wrote:
Wow, thanks! I think this is what I needed to get something resolved here. I actually did something *very* similar to the code you wrote (I think there's a sample of something like this buried in the program_options docs somewhere) and totally forgot. Taking a fresh look at the compilation error, I see that it passes through this function in the middle of the template instantiation stack, so this is almost certainly involved in the problem. Now, why my `validate` function only fails when I'm using MSVC (I tested it on VS2017 and it still happens there) with boost::optional (as opposed to std::optional) and Boost 1.62+, I'm still not sure. It's possible there's still a bug here, but I'll have to continue investigating. - Jim

On 6/5/2018 8:51 AM, Xavier Besseron wrote:
I finally got everything working, and based on your code, you'll have the same issue if you start using Boost 1.62+ on MSVC. I didn't delve too deep into the why, but putting your `validate` function in the `boost` namespace and `using namespace boost::program_options` will introduce an ambiguity when constructing a `boost::optional` (it's trying to find the `detail` namespace and gets confused). I resolved it like this: <https://github.com/jimporter/mettle/blob/7ea222a58537bd366ec0cf864de30d2969563d41/include/mettle/driver/cmd_line.hpp#L116-L131>. Thanks again for the pointer! - Jim

On 5 June 2018 at 18:51, Xavier Besseron via Boost-users < boost-users@lists.boost.org> wrote:
I hope this will help.
Maybe you should/could create a PR, then in the future (if and when it get's merged, you don't have to fiddle with the boost code either). Have a good day, degski -- *"If something cannot go on forever, it will stop" - Herbert Stein*

On 6/5/2018 8:50 PM, degski via Boost-users wrote:
Code similar to what Xavier posted is in Boost 1.65+, but if you want to support earlier versions of Boost (or use std::optional instead of boost::optional), you have to do something like that. It would probably be worth adding an overload that works with std::optional, but I don't know if I'll have time in the near future to shepherd a patch into Boost. - Jim
participants (4)
-
Chris Glover
-
degski
-
Jim Porter
-
Xavier Besseron