Ill-formed C++0x code or compiler bug (GCC) ?

S

SG

Hi!

In the following C++0x code I tried to clone an object by using a
clone member function (if it exists) and falling back on a copy
constructor:

#include <type_traits>

struct use_copy_ctor {};
struct prefer_clone_func : use_copy_ctor {};

template<class T>
auto clone(T const* ptr, prefer_clone_func)
-> decltype(ptr->clone())
{ return ptr->clone(); }

template<class T>
auto clone(T const* ptr, use_copy_ctor)
-> decltype(new T(*ptr))
{ return new T(*ptr); }

struct abc {
virtual ~abc() {}
virtual abc* clone() const =0;
};

struct derived : abc
{
derived* clone() const { return new derived(*this); }
};

int main()
{
derived d;
abc* p = &d;
abc* q = clone(p,prefer_clone_func());
delete q;
}

The idea is to use auto...->decltype(expr) to weed out ill-formed
expressions as part of the template argument deduction (SFINAE) and to
resolve a possible ambiguity between both clone function templates via
partial ordering w.r.t. the second function parameter.

Unfortunately, GCC 4.5.1 doesn't accept this program:

test.cpp: In function 'int main()':
test.cpp:30:39: error: cannot allocate an object of abstract type
'abc'
test.cpp:16:12: note: because the following virtual functions are
pure within 'abc':
test.cpp:18:16: note: virtual abc* abc::clone() const
test.cpp:30:39: error: cannot allocate an object of abstract type
'abc'
test.cpp:16:12: note: since type 'abc' has pure virtual functions

Now, the question is, is this a compiler bug or was I wrong to assume
that SFINAE applies here?

Cheers!
SG
 
S

SG

In the following C++0x code I tried to clone an object by using a
clone member function (if it exists) and fall back on a copy
constructor:

[...]

Unfortunately, GCC 4.5.1 doesn't accept this program:

[...]

Now, the question is, is this a compiler bug or was I wrong to assume
that SFINAE applies here?

I convinced myself that this is another case where GCC ignores the
"NAE" in SFINAE in combination with templates and decltype and filed a
bug report:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47513

Cheers!
SG
 
M

Marc

SG said:
In the following C++0x code I tried to clone an object by using a
clone member function (if it exists) and falling back on a copy
constructor:

#include <type_traits>

What for?
struct use_copy_ctor {};
struct prefer_clone_func : use_copy_ctor {};

template<class T>
auto clone(T const* ptr, prefer_clone_func)
-> decltype(ptr->clone())
{ return ptr->clone(); }

template<class T>
auto clone(T const* ptr, use_copy_ctor)
-> decltype(new T(*ptr))
{ return new T(*ptr); }

struct abc {
virtual ~abc() {}
virtual abc* clone() const =0;
};

struct derived : abc
{
derived* clone() const { return new derived(*this); }
};

int main()
{
derived d;
abc* p = &d;
abc* q = clone(p,prefer_clone_func());
delete q;
}

The idea is to use auto...->decltype(expr) to weed out ill-formed
expressions as part of the template argument deduction (SFINAE) and to
resolve a possible ambiguity between both clone function templates via
partial ordering w.r.t. the second function parameter.

Unfortunately, GCC 4.5.1 doesn't accept this program:

clang++ accepts it. It gained a lot of C++0x features last week, now
it is just missing a library so we can start playing with it... (it
can't handle the C++0x parts of libstdc++ and libc++ only works on
Mac)
 
S

SG

SG  wrote:


What for?

Nothing, actually. It's a relict from previous versions. I removed
this line before submitting the bug report. Initially, I used
enable_if in combination with is_constructible<T,T const&>::value but
libstdc++'s current implementation of is_constructible also "chokes"
on abstract class types. I guess this is due to the same SFINAE<-
decltype issue I ran into (assuming is_constructible was implemented
in terms of SFINAE+decltype).
clang++ accepts it. It gained a lot of C++0x features last week,
Great!

now it is just missing a library so we can start playing with it...
(it can't handle the C++0x parts of libstdc++
and libc++ only works on Mac)

Huh. I wouldn't have expected that.

Cheers!
SG
 
D

Dilip

Hi!

In the following C++0x code I tried to clone an object by using a
clone member function (if it exists) and falling back on a copy
constructor:

   #include <type_traits>

   struct use_copy_ctor {};
   struct prefer_clone_func : use_copy_ctor {};

   template<class T>
   auto clone(T const* ptr, prefer_clone_func)
   -> decltype(ptr->clone())
   { return ptr->clone(); }

   template<class T>
   auto clone(T const* ptr, use_copy_ctor)
   -> decltype(new T(*ptr))
   { return new T(*ptr); }

   struct abc {
     virtual ~abc() {}
     virtual abc* clone() const =0;
   };

   struct derived : abc
   {
     derived* clone() const { return new derived(*this); }
   };

   int main()
   {
     derived d;
     abc* p = &d;
     abc* q = clone(p,prefer_clone_func());
     delete q;
   }

The idea is to use auto...->decltype(expr) to weed out ill-formed
expressions as part of the template argument deduction (SFINAE) and to
resolve a possible ambiguity between both clone function templates via
partial ordering w.r.t. the second function parameter.

Unfortunately, GCC 4.5.1 doesn't accept this program:

test.cpp: In function 'int main()':
test.cpp:30:39: error: cannot allocate an object of abstract type
'abc'
test.cpp:16:12: note:   because the following virtual functions are
pure within 'abc':
test.cpp:18:16: note:        virtual abc* abc::clone() const
test.cpp:30:39: error: cannot allocate an object of abstract type
'abc'
test.cpp:16:12: note:   since type 'abc' has pure virtual functions

Now, the question is, is this a compiler bug or was I wrong to assume
that SFINAE applies here?

Cheers!
SG

VC++ 2010 fails with a *linker* error:

error LNK2019: unresolved external symbol "public: __thiscall
abc::abc(void)" (??0abc@@QAE@XZ) referenced in function "public:
__thiscall derived::derived(void)" (??0derived@@QAE@XZ)
 
S

SG

VC++ 2010 fails with a *linker* error:

error LNK2019: unresolved external symbol "public: __thiscall
abc::abc(void)" (??0abc@@QAE@XZ) referenced in function "public:
__thiscall derived::derived(void)" (??0derived@@QAE@XZ)

That's weird. Looks like VC++ forgot to emit the definition of the
"compiler-generated" default constructor of abc.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top