Topic: Inline member function referencing unimplemented singleton


Author: "Daniel Parker" <danielp@no_spam.com>
Date: 1999/03/31
Raw View
Supose I have a class Handle with two inlined constructors, viz.

class Handle
{
public:
    Handle( Body* pBody )
        : d_pBody(pBody)
    {
    }
    Handle( const std::string& name )
    {
 d_pBody = Registry::createByName( name );
    }
private:
    Body* d_pBody;
};

Now suppose I have a library that contains no implementation of Registry
but that does create Handles using the first constructor.  If I create a
little application and link to this library, can I rely on not getting an
unresolved external error for Registry?

Regards,
Daniel Parker danielp@no_spam.anabasis.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/04/01
Raw View
"Daniel Parker" <danielp@no_spam.com> writes:

>Supose I have a class Handle with two inlined constructors, viz.
>
>class Handle
>{
>public:
>    Handle( Body* pBody )
>        : d_pBody(pBody)
>    {
>    }
>    Handle( const std::string& name )
>    {
> d_pBody = Registry::createByName( name );
>    }
>private:
>    Body* d_pBody;
>};
>
>Now suppose I have a library that contains no implementation of Registry
>but that does create Handles using the first constructor.  If I create a
>little application and link to this library, can I rely on not getting an
>unresolved external error for Registry?

No.  See 3.2 One definition rule [basic.def.odr]:

 | -2- An expression is _potentially_evaluated_ unless either it is the
 | operand of the sizeof operator (expr.sizeof), or it is the operand of
 | the typeid operator and does not designate an lvalue of polymorphic
 | class type (expr.typeid).

This means that the expression `Registry::createbyName(name)'
is _potentially_evaluated_.

 | An object or non-overloaded function is _used_
 | if its name appears in a potentially-evaluated expression.
 ...
 | An overloaded function is used if it is selected by overload
 | resolution when referred to from a potentially-evaluated expression.

This means that the function `Registry::createbyName' is _used_.

 | -3- Every program shall contain exactly one definition of every
 | non-inline function or object that is used in that program; no
 | diagnostic required. The definition can appear explicitly in the
 | program, it can be found in the standard or a user-defined library, or
 | (when appropriate) it is implicitly defined (see class.ctor,
 | class.dtor and class.copy). An inline function shall be defined in
 | every translation unit in which it is used.

Since `Registry::createbyName' is _used_ in your program, the above
text means that your program must contain a definition of
`Registry::createbyName'.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3        |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]