Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3-parameter CommandLineOption constructor overloads are ambiguous #215

Closed
WebDrake opened this issue Mar 2, 2018 · 3 comments
Closed

3-parameter CommandLineOption constructor overloads are ambiguous #215

WebDrake opened this issue Mar 2, 2018 · 3 comments
Assignees

Comments

@WebDrake
Copy link

WebDrake commented Mar 2, 2018

When building on bionic, I get compilation errors when trying to use the various 3-parameter overloads of the CommandLineOption constructor, i.e. those overloads that do not include a default_value parameter:
https://github.com/MirServer/mir/blob/38ec6376284a88f94fd69f5c9e86fdc57a7a5a08/include/miral/miral/command_line_option.h#L72-L90

Specifically, if a lambda is provided to the constructor, the compiler appears unable to work out which std::function<void(T)> template instantiation is to be used.

The following simple test program can be used to illustrate the problem:

#include <miral/command_line_option.h>
#include <iostream>

int main(void)
{
    // ambiguous between all four possible 3-parameter overloads
    auto bool_flag = miral::CommandLineOption(
        [](bool is_set)
	{
	    std::cerr << "Boolean flag" << std::endl;
	},
	"bool", "Set a boolean flag");

    // ambiguous between `void(bool)`, `void(mir::optional_value<bool> const&)`
    // and `void(mir::optional_value<int> const&)`
    auto optional_bool_flag = miral::CommandLineOption(
        [](mir::optional_value<bool> const& value)
        {
            std::cerr << "Optional boolean flag" << std::endl;
        },
        "optional-bool", "Set an optional boolean flag");

    // ambiguous between `void(bool)` vs. `void(mir::optional_value<int> const&)`
    auto optional_int_flag = miral::CommandLineOption(
        [](mir::optional_value<int> const& value)
        {
            std::cerr << "Optional int flag" << std::endl;
        },
        "optional-int", "Set an optional int flag");

    // works
    auto optional_string_flag = miral::CommandLineOption(
        [](mir::optional_value<std::string> const& value)
        {
            std::cerr << "Optional string flag" << std::endl;
        },
        "optional-string", "Set an optional string flag");
}

(Build with e.g. g++ -I/usr/include/mircore -I/usr/include/miral/ -c commandlineoption.cpp to see the errors.)

The problem does not show up when building on xenial, and does not appear to be related to the g++ version in use.

The best workaround I can find is to pass an explicit std::function instance to the CommandLineOption compiler, e.g.:

    auto bool_flag = miral::CommandLineOption(
        std::function<void(bool)>([](bool is_set)
	{
	    std::cerr << "Boolean flag" << std::endl;
	}),
	"bool", "Set a boolean flag");
@WebDrake
Copy link
Author

WebDrake commented Mar 2, 2018

Hmmm, with the minimal example alone, this does show up on xenial, even though the original point of discovery (when modifying unity-system-compositor) did not.

WebDrake added a commit to WebDrake/unity-system-compositor that referenced this issue Mar 6, 2018
This method of handling `--version` removes some of the custom arguments
handling blocking the transition to using `miral::MirRunner`.

The explicit use of `std::function<void(bool)>` is required in order to
avoid ambiguity about the compiler overload being invoked; for details,
see canonical/mir#215.
WebDrake added a commit to WebDrake/unity-system-compositor that referenced this issue Mar 6, 2018
This patch reworks the creation of the `DMConnection` instance used in
USC, extracting it from the init callback added under the hood of the
`SystemCompositor` class, and placing it instead in `main`, where it is
instantiated using a collection of `CommandLineOption` instances.  Most
of the latter are implemented using `pre_init` just to ensure that the
resulting values are set correctly before the display manager connection
itself is instantiated; only the `--debug-without-dm` flag is not, since
its callback is the one inside which the instantiation actually happens.
(The use of `pre_init` for the others is probably overkill, but it can't
hurt to make sure that these values are handled as early as possible.)

This allows us to clean up some uses of `add_configuration_option` and
so reduce the number of direct dependencies on the `mir::Server` API.
We can also now remove the explicit `SystemCompositor` constructor, as
the class no longer needs to access the session switcher.

The explicit use of `std::function<void(bool)>` is required in order to
avoid ambiguity about the compiler overload being invoked; for details,
see canonical/mir#215.
@AlanGriffiths AlanGriffiths self-assigned this Mar 8, 2018
@AlanGriffiths
Copy link
Collaborator

Hmm... Why didn't this connect to PR #228

bors bot added a commit that referenced this issue Mar 8, 2018
228: miral::CommandLineOption should accept lambdas (Fixes #215) r=wmww a=AlanGriffiths
@WebDrake
Copy link
Author

WebDrake commented Mar 8, 2018

I think it may be that you need the Fixes #XXX in the PR description (not the title). Anyway, thanks! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants