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

Wrapper std::any not copy constructible #40268

Open
JVApen opened this issue Mar 1, 2019 · 5 comments
Open

Wrapper std::any not copy constructible #40268

JVApen opened this issue Mar 1, 2019 · 5 comments
Labels
bugzilla Issues migrated from bugzilla clang Clang issues not falling into any other category

Comments

@JVApen
Copy link

JVApen commented Mar 1, 2019

Bugzilla Link 40923
Version trunk
OS Windows NT
CC @JVApen,@zygoloid

Extended Description

Following is a reduction of an MSVC usage.

Following code compiles with GGC/MSVC, not with clang: https://gcc.godbolt.org/z/ii2e2E

t.cpp

#include <any>
#include <type_traits>

struct V
{
    V(std::any a) : a{a} {}
    ~V() = default;

    V(const V &) = default;

    std::any a;
};

static_assert(std::is_copy_constructible_v<V>);

run.sh

clang++ -O0  -std=c++17 -w -Wunused-variable t.cpp
@llvmbot
Copy link
Member

llvmbot commented Mar 13, 2019

This bug also effects version 6 and 7.

I filed this as a question on stack overflow (https://stackoverflow.com/questions/55107458/problem-trying-to-call-copy-constructor-in-base-class-which-has-a-stdany-const) before realizing it was actually a bug. Now I'm stuck using gcc until it's fixed. :-(

@JVApen
Copy link
Author

JVApen commented May 2, 2019

Correcting 'enhancement' to 'normal' issue. This ain't a feature request.

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Aug 1, 2019

I suspect this is not a bug. I expect what's happening is this:

  • std::is_copy_constructible<V> considers a V(declval<const V&>()) construction
  • that construction considers calling the V(std::any) constructor
  • that in turn considers a std::any = declval<const V&>() copy-initialization for the constructor's parameter
  • that in turn considers a std::any constructor that has a constraint involving std::is_copy_constructible<V> (because any can only store copy-constructible values)

So computation of std::is_copy_constructible<V> recursively involves its own value, resulting in the error that Clang produces (no member value in is_copy_constructible, because we've not instantiated it yet).

Note that GCC trunk now rejects this code in the same way that Clang does, as the godbolt link in comment#0 shows. (Clang with -stdlib=libc++ happens to accept it, but I think we're just getting lucky there and don't happen to look at std::is_copy_constructible<V> when constructing the std::any.)

The best fix is probably to constrain the V(std::any) constructor so that it's not considered when copying from a value of type V. Eg:

  template<typename T,
           typename = std::enable_if_t<!std::is_same_v<std::remove_cvref_t<T>, V>>>
  V(T &&t) : a{std::forward<T>(t)} {}

Such "don't consider this for copying!" constraints are generally needed when writing converting constructors that convert from anything.

@JVApen
Copy link
Author

JVApen commented Aug 3, 2019

@​Richard: I see the argument for constraining this code the way you suggest. However, I don't see why this code shouldn't compile.
As far as I understand c++, overload resolution should take the exact match over implicit conversions. As a const V & overload exists, it should take that one instead of doing an implicit conversion to std::any. It's a different story if I would be using V & (which get's fixed with your suggestion).

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
@Fedr
Copy link

Fedr commented Jan 26, 2022

Probably the same issue:

#include <any>
#include <type_traits>

struct A {
    A(const A&) = default;
    explicit A(std::any value);
};
static_assert(std::is_copy_constructible_v<A>);

It is accepted in Clang 13, but not in Clang trunk. The error is

type_traits:168:14: error: base class has incomplete type
    : public __conditional_t<_B1::value, _B2, _B1>
      ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/

Demo: https://gcc.godbolt.org/z/hrGY5dEjK

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla clang Clang issues not falling into any other category
Projects
None yet
Development

No branches or pull requests

3 participants