Should this short (but abstruse) program compile?

H

Howard Gardner

/*

As it sits, this program won't compile for me. It will compile
using either of the versions of tpt that I've commented out.
Which versions SHOULD compile?

I think that the code is interesting because I think that it is
on the path to building a useful non-intrusive type introspection
facility. The version that uses "has" indicates the direction.

*/
#include <ostream>
#include <cstddef>

template< typename x >
x * faux_ptr();

//template< typename x, size_t = sizeof( int * ) >
// struct tpt{};

//template< typename x, size_t = sizeof( faux_ptr< int >() ) >
// struct tpt{};

//struct has{ int memvar; };
//template< typename x, size_t = sizeof( faux_ptr< has >()->memvar ) >
// struct tpt{};

template< typename x, size_t = sizeof( faux_ptr< x >() ) >
struct tpt{};

template< typename x >
bool fnc( tpt< x > );

tpt< int > inst;

size_t size = sizeof( fnc( inst ) );

int main()
{
using namespace std;
cout << size << endl;
}
 
V

Victor Bazarov

Howard said:
/*

As it sits, this program won't compile for me. It will compile
using either of the versions of tpt that I've commented out.
Which versions SHOULD compile?

I think that the code is interesting because I think that it is
on the path to building a useful non-intrusive type introspection
facility. The version that uses "has" indicates the direction.

*/
#include <ostream>
#include <cstddef>

template< typename x >
x * faux_ptr();

//template< typename x, size_t = sizeof( int * ) >
// struct tpt{};

//template< typename x, size_t = sizeof( faux_ptr< int >() ) >
// struct tpt{};

//struct has{ int memvar; };
//template< typename x, size_t = sizeof( faux_ptr< has >()->memvar ) >
// struct tpt{};

template< typename x, size_t = sizeof( faux_ptr< x >() ) >
struct tpt{};

Why don't you simply make it

template< typename x, size_t = sizeof( x* ) >
struct tpt{};

Isn't it the same?

Incidentally, the original code compiles fine for me with VC++ 2005
and doesn't compile with online Comeau trial.
template< typename x >
bool fnc( tpt< x > );

It might be a mistake to try to rely on the default template argument
here. The syntax 'tpt< x >' here might not give the compiler good enough
a hint so it knows to use the default arg. Have you tried


template< typename x, size_t s >
bool fnc( tpt< x,s > );

? Comeau compiles the code in this case.
tpt< int > inst;

size_t size = sizeof( fnc( inst ) );

int main()
{
using namespace std;
cout << size << endl;
}

V
 
H

Howard Gardner

One more try :(

Victor said:
>
> Why don't you simply make it
>
> template< typename x, size_t = sizeof( x* ) >
> struct tpt{};
>
> Isn't it the same?

Yes.

I need to know why the code that I posted fails, though, because I think
that the code I'm actually interested in fails for the same reason.

What I really want to write is:

template< typename x, size_t = sizeof( faux_ptr< x >()->memvar ) >
struct tpt{};

The reason I want to write that gets even more abstruse (see
my recent posts in c.l.c.moderated if you're interested).
>
> Incidentally, the original code compiles fine for me with VC++ 2005

Interesting. There's another version below for you to try if you're willing.
> and doesn't compile with online Comeau trial.

I'm using Comeau. Every time that I've thought it was misbehaving I've
turned out to be wrong. I fully expect to learn that's the case again.
>
>
> It might be a mistake to try to rely on the default template argument
> here. The syntax 'tpt< x >' here might not give the compiler good enough
> a hint so it knows to use the default arg. Have you tried
>
>
> template< typename x, size_t s >
> bool fnc( tpt< x,s > );

The entire point of the exercise is to make the compiler evaluate the
sizeof in the default template argument.

Here's a version that's more closely related to my motivation.

#include <ostream>
#include <cstddef>

struct has{ int memvar; };
struct hasnt{};

template< typename x >
x * faux_ptr();

template< typename x, size_t = sizeof( faux_ptr< x >()->memvar ) >
struct tpt{};

typedef char no;
struct yes{ no val[2]; };

template< typename x >
no fnc( ... );

template< typename x >
yes fnc( tpt< x > * );

int main()
{
using namespace std;
cout << sizeof( fnc< has >( 0 ) ) << endl;
cout << sizeof( fnc< hasnt >( 0 ) ) << endl;
}

On my compiler, sizeof( no ) is 1, and sizeof( yes ) is 2. It prints:

1
1

Which means that it selects the "no" version of fnc both times.

If tpt is well formed, it should select the "yes" version of fnc and print:

2
1
 
V

Victor Bazarov

Howard said:
[...]
Incidentally, the original code compiles fine for me with VC++ 2005

Interesting. There's another version below for you to try if you're
willing.
Sure.
and doesn't compile with online Comeau trial.

I'm using Comeau. Every time that I've thought it was misbehaving I've
turned out to be wrong. I fully expect to learn that's the case again.

It makes sense to contact them directly if you have a question about
some behavoiur of their compiler. They are very knowledgeable in C++
and can describe to you what parts of the Standard apply in such cases.
[...]

On my compiler, sizeof( no ) is 1, and sizeof( yes ) is 2. It prints:

1
1

So does it on VC++ 2005.
Which means that it selects the "no" version of fnc both times.

If tpt is well formed, it should select the "yes" version of fnc and
print:
2
1

I have no explanation to share, sorry. But it's an interesting case.
Once you get it resolved, post your results please, for everybody's
benefit. Thanks!

V
 

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

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top