Typeid and forward declaration - Clarification needed

Hi all,

This is with respect to the following TC.

struct S;

template
static bool fn (S *s)
{
return typeid (*s) == typeid (T);
}

struct S
{
};

bool x = fn (__null);

The standard says:
If the type of the type-id is a class type or a reference to a class type, the class shall be completely-defined.

This “shall” is kind of confusing. Is this a valid TC. Is forward declaration allowed while using the typeid operator?

Any clarification on the same would be appreciated.

Thanks,

Rahul

--- end quoted text ---

Hi Rahul,
That test case does work on g++-4.8.1. The reason is that fn is a template function.
And the compiler does not instantiate it until it is needed. That is down at the call
site, 'bool x = fn<S>(__null);', where the full definition of struct S is in scope.

If you refactor fn to be a plain function, then you will get the error due to use
of an incomplete type 'struct S'.

enjoy,
Karen

Hi all,

This is with respect to the following TC.

struct S;

template <typename T>
static bool fn (S *s)
{
  return typeid (*s) == typeid (T);
}

struct S
{
};

bool x = fn<S> (__null);

The standard says:
If the type of the type-id is a class type or a reference to a class type,
the class shall be completely-defined.

This "shall" is kind of confusing. Is this a valid TC. Is forward
declaration allowed while using the typeid operator?

No, but the rules are slightly different because this occurs inside a
template. This testcase is ill-formed, but no diagnostic is required, per
[temp.res](14.6)p8:

"If a type used in a non-dependent name is incomplete at the point at which
a template is defined but is complete at the point at which an
instantiation is done, and if the completeness of that type affects whether
or not the program is well-formed or affects the semantics of the program,
the program is ill-formed; no diagnostic is required."

So the template has no valid specializations. Further, we're allowed to
reject this even if the template is never instantiated:

"If no valid specialization can be generated for a template, and that
template is not instantiated, the template is ill-formed, no diagnostic
required."

Hi Richard,
There is no ambiguity there. The standard defines it concisely. I actually thought
whether a compiler rejected that example was implementation specific, depending on
the compiler's template instantiation stategy. But c++11 defines it as an ill-formed
program. Is that test case an ill-formed program in the previous standard?

enjoy,
Karen

The wording was added by DR206 in response to the ambiguity in the original
(C++98) spec. Since this was a DR, it retroactively applies to C++98 too,
so this code has (in some sense) always been ill-formed, with no diagnostic
required:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#206

I'm not sure what you're talking about when you mention ambiguity.

Hi Richard,
I simply meant the standard is clear and concise as you point out. And this
issue has nothing to do with the discretion of the implementation. It is an
ill-formed program. Thank you very much for clarifying the details. Very helpful.

enjoy,
Karen

I work with Ubuntu 13.10 these days and am quite pleased to learn clang-3.3 is supported
by Ubuntu Saucy universe repositories.

root@ip-212-12-37-96:/etc/apt# dpkg --get-selections | grep llvm
libllvm3.3:amd64 install
llvm-3.3 install
llvm-3.3-dev install
llvm-3.3-doc install
llvm-3.3-runtime install
root@ip-212-12-37-96:/etc/apt# dpkg --get-selections | grep clang
clang-3.3 install
libclang-common-3.3-dev install
libclang1-3.3 install

My understanding is clang-3.3 provides full support for c++11 standard. That is one of my
requirements. Next step is to do comparison testing on performance of compiled binaries.
That is a critically important metric I am looking at.

enjoy,
Karen

$ ldd /usr/bin/clang
  linux-vdso.so.1 => (0x00007fffc99fe000)
  libLLVM-3.3.so.1 => /usr/lib/x86_64-linux-gnu/libLLVM-3.3.so.1 (0x00007f41cfe0d000)
  libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f41cfbf0000)
  libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f41cf8eb000)
  libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f41cf6d5000)
  libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f41cf30d000)
  libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f41cf104000)
  libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f41cef00000)
  libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f41cebfc000)
  /lib64/ld-linux-x86-64.so.2 (0x00007f41d148b000)

I guess you need to roll your own to use libc++. Even so, it is a great jumping off point
to have all this available on Ubuntu Saucy without needing to be a pioneer. Maybe I'll use
this compiler to start a bootstrap of the 3.4 release in January.

enjoy,
Karen

This tool chain doesn't actually work out of the box on Ubuntu. I see clang needs
binutils-gold. I am OK with that. But after looking into it, I apparently need to break
my default GNU tool chain to use it. I am not willing to do that.

enjoy,
Karen

Of course, I can grab all the sources and build my own clang/llvm tool chain, and then I can
configure the build to coexist with the default GNU tool chain. But then I would be maintaining
that tool chain. Not something I want to invest in right now. Eventually, I'll do that.

But even with these Ubuntu packages, the compiler does work. And I can compile without
linking, enabling me to see all the error and warning messages clang emits. And this has
been an eye opener -- to compile code with 'g++ -Wall -std=c++11' and then to compile
the same code with clang. Its becoming quite clear very quickly there is a world of
difference in these two compilers in the context of errors and warnings. Shocking what
I am seeing. +1 to clang/llvm in this context.

enjoy,
Karen