Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8607019
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 12, 20262026-06-12T03:14:28+00:00 2026-06-12T03:14:28+00:00

Consider this minimal example: #include <memory> struct B { typedef std::shared_ptr<B> Ptr; }; struct

  • 0

Consider this minimal example:

#include <memory>

struct B {
  typedef std::shared_ptr<B> Ptr;
};

struct A {
  operator B::Ptr() { // type conversion operator                  <----+
    return std::make_shared<B>();  //                                   |
  }                                //                                   |
};                                 //                                   |
                                   //                                   |
int main() {                       //                                   |
  A* a = new A;                    //                                   |
  B::Ptr{*a}; // copy construction from a's implicit cast to B::Ptr ----+ 
}

This innocent copy construction of a shared_ptr<B> fails horribly on g++ 4.6.3 x86_64-linux-gnu but appears to work for g++ 4.5 (note that the newer version breaks, while the older works!). From what I can tell from the error (see below) g++ 4.6 seems to pass A by value, instead of by (r or l) reference.

So, the question is, which is correct and which is broken? Is this behaviour supposed to fail? If so, why?
As far as I understand conversion rules, the implicit cast to B::Ptr should be attempted at this point, right?


Note: I reduced this example to the bare technical problem, and this code doesn’t make sense for any production-system as it stands.

Here is the precise error:

shp.cpp: In function ‘int main()’:
shp.cpp:17:12: error: no matching function for call to ‘std::shared_ptr<B>::shared_ptr(<brace-enclosed initializer list>)’
shp.cpp:17:12: note: candidates are:
/usr/include/c++/4.6/bits/shared_ptr.h:315:2: note: template<class _Alloc, class ... _Args> std::shared_ptr::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...)
/usr/include/c++/4.6/bits/shared_ptr.h:266:17: note: constexpr std::shared_ptr<_Tp>::shared_ptr(std::nullptr_t) [with _Tp = B, std::nullptr_t = std::nullptr_t]
/usr/include/c++/4.6/bits/shared_ptr.h:266:17: note:   no known conversion for argument 1 from ‘A’ to ‘std::nullptr_t’
/usr/include/c++/4.6/bits/shared_ptr.h:258:2: note: template<class _Tp1, class _Del> std::shared_ptr::shared_ptr(std::unique_ptr<_Up, _Ep>&&)
/usr/include/c++/4.6/bits/shared_ptr.h:253:2: note: template<class _Tp1> std::shared_ptr::shared_ptr(std::auto_ptr<_Tp1>&&)
/usr/include/c++/4.6/bits/shared_ptr.h:248:11: note: template<class _Tp1> std::shared_ptr::shared_ptr(const std::weak_ptr<_Tp1>&)
/usr/include/c++/4.6/bits/shared_ptr.h:236:2: note: template<class _Tp1, class> std::shared_ptr::shared_ptr(std::shared_ptr<_Tp1>&&)
/usr/include/c++/4.6/bits/shared_ptr.h:226:7: note: std::shared_ptr<_Tp>::shared_ptr(std::shared_ptr<_Tp>&&) [with _Tp = B, std::shared_ptr<_Tp> = std::shared_ptr<B>]
/usr/include/c++/4.6/bits/shared_ptr.h:226:7: note:   no known conversion for argument 1 from ‘A’ to ‘std::shared_ptr<B>&&’
/usr/include/c++/4.6/bits/shared_ptr.h:218:2: note: template<class _Tp1, class> std::shared_ptr::shared_ptr(const std::shared_ptr<_Tp1>&)
/usr/include/c++/4.6/bits/shared_ptr.h:206:2: note: template<class _Tp1> std::shared_ptr::shared_ptr(const std::shared_ptr<_Tp1>&, _Tp*)
/usr/include/c++/4.6/bits/shared_ptr.h:184:2: note: template<class _Deleter, class _Alloc> std::shared_ptr::shared_ptr(std::nullptr_t, _Deleter, _Alloc)
/usr/include/c++/4.6/bits/shared_ptr.h:165:2: note: template<class _Tp1, class _Deleter, class _Alloc> std::shared_ptr::shared_ptr(_Tp1*, _Deleter, _Alloc)
/usr/include/c++/4.6/bits/shared_ptr.h:146:2: note: template<class _Deleter> std::shared_ptr::shared_ptr(std::nullptr_t, _Deleter)
/usr/include/c++/4.6/bits/shared_ptr.h:129:2: note: template<class _Tp1, class _Deleter> std::shared_ptr::shared_ptr(_Tp1*, _Deleter)
/usr/include/c++/4.6/bits/shared_ptr.h:112:11: note: template<class _Tp1> std::shared_ptr::shared_ptr(_Tp1*)
/usr/include/c++/4.6/bits/shared_ptr.h:103:7: note: std::shared_ptr<_Tp>::shared_ptr(const std::shared_ptr<_Tp>&) [with _Tp = B, std::shared_ptr<_Tp> = std::shared_ptr<B>]
/usr/include/c++/4.6/bits/shared_ptr.h:103:7: note:   no known conversion for argument 1 from ‘A’ to ‘const std::shared_ptr<B>&’
/usr/include/c++/4.6/bits/shared_ptr.h:100:17: note: constexpr std::shared_ptr<_Tp>::shared_ptr() [with _Tp = B]
/usr/include/c++/4.6/bits/shared_ptr.h:100:17: note:   candidate expects 0 arguments, 1 provided
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-12T03:14:31+00:00Added an answer on June 12, 2026 at 3:14 am

    The code is incorrect under the current version of the standard (I’m looking at post-standard draft n3376).

    The rules for list-initialization specify:

    13.3.1.7 Initialization by list-initialization [over.match.list]

    1 – When objects of non-aggregate class type T are list-initialized […]:

    • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

    However, when overload resolution is applied to the copy constructor of B::Ptr taking the single parameter const std::shared_ptr<B> &, the argument list is (*a), consisting of a single element of type lvalue A; overload resolution is not permitted to consider the conversion function A::operator B::Ptr:

    13.3.3.1 Implicit conversion sequences [over.best.ics]

    4 – However, when considering the argument of a constructor or user-defined conversion function that is a candidate […] by 13.3.1.7 […] when the initializer list has exactly one element and a conversion to some class X or reference to (possibly cv-qualified) X is considered for the first parameter of a constructor of X […], only standard conversion sequences and ellipsis conversion sequences are considered.

    So g++-4.6 is correct to reject this code; g++-4.7.2 unfortunately accepts it, which is incorrect.

    The correct way to write this would be to use direct-initialization (B::Ptr(*a)) or a static_cast<B::Ptr>.

    The restriction on the allowable conversions can be traced to paper n2672, although in that paper the paragraph 13.3.3.1p4 only applies to the argument of a user-defined conversion function. The additional restriction on constructors was added in defect 978:

    978. Incorrect specification for copy initialization

    13.3.3.1 [over.best.ics] paragraph 4 says,
    […]
    This is not quite right, as this applies to constructor arguments, not just arguments of user-defined conversion functions.

    The current wording of 13.3.3.1p4 can be traced to the seminal defect 84, which introduced the "common-law rule that only a single user-defined conversion will be called to do an implicit conversion".

    I’m a bit uneasy about this answer; I’ve asked Is it possible to invoke a user-defined conversion function via list-initialization? to see if anyone can clarify the intent of the standard here.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Consider this minimal example: #include <array> struct X { std::array<int,2> a; X(int i, int
Consider this code: #include <iostream> using namespace std; typedef int array[12]; array sample; array
Consider the following minimal example: #include <iostream> using namespace std; class myostream : public
Consider this example code: #include <iostream> class base { public: base() { std::cout <<
Consider this template function: template<typename ReturnT> ReturnT foo(const std::function<ReturnT ()>& fun) { return fun();
Consider this contrived, trivial example: var foo = new byte[] {246, 127}; var bar
Consider this small program: #include <stdio.h> #include <stdlib.h> // Change 60000 to 70000 and
Consider this simple example - public class Person { private String name; private Date
Consider this example var task =Task.Factory.StartNew(()=>Console.WriteLine(test)); task.ContinueWith(antecendent => { ExceptionProcessor.HandleError(task.Exception.Flatten()); }, TaskContinuationOptions.OnlyOnFaulted); In this
Consider this very simple example, where I have template wrapper class for which are

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.