Hi.I have a piece of code that compiles without even a warning on the borland 5.5 compiler yet complains bitterly when compiling with g++.I've heard that g++ emits more portable code but shouldn't they both be standard compliant?From what i've read in the '98 standard book this should be legal but feel free to prove me wrong.Thanks

#include <iostream>
#include <string>

template <const char* type=NULL> struct asd  {
   static const char* str;
   std::string strng;
   asd () : strng(type) {}
   ~asd () {}
   operator std::string ()  {
      return strng;
    }
 };

template <const char*> const char* asd<>::str="asd";
typedef asd<asd<>::str> Asd;

int main ()  {
   Asd s;
   std::cout << std::string(s);
 }

G++ spitting fire:

asd.cpp:14:40: error: could not convert template argument ‘0’ to ‘const char*’
asd.cpp:14:43: error: template declaration of ‘const char* str’
asd.cpp:15:17: error: could not convert template argument ‘0’ to ‘const char*’
asd.cpp:15:23: error: template argument 1 is invalid
asd.cpp:15:28: error: invalid type in declaration before ‘;’ token
asd.cpp: In function ‘int main()’:
asd.cpp:19:32: error: invalid conversion from ‘Asd’ to ‘const char*’
asd.cpp:19:32: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]’

>>I've heard that g++ emits more portable code but shouldn't they both be standard compliant?

Standard compliant? That's an ideal, not a reality. The only compiler that exists which is fully compliant to the C++98 standard is the Comeau compiler (and it took significant efforts to make it compliant, which was done just recently). Compilers are not, in general, compliant to the standard, strictly speaking. They all have their own "features". But yes, GCC tends to be, amongst the popular compilers, the most standard compliant one. At least, usually what the standard permits, GCC permits, with few exceptions, but GCC is also more permissive than the standard in some ways, most other compilers are too.

When it comes to programming with templates, that's where the differences between compilers tend to show up a lot more than in "normal" programming.

>>From what i've read in the '98 standard book this should be legal but feel free to prove me wrong.

You are right, it is legal, I mean the main part about using a char-pointer as template argument. Except that you made an error in your static constant definition, I'm guessing you meant to write:

template <const char* type> 
const char* asd<type>::str = "asd";

Now, lets take a look at those errors:

>>error: could not convert template argument ‘0’ to ‘const char*’

This is just a technicality, GCC doesn't seem to want to do integral to pointer casts in a template argument. GCC probably defines NULL as just 0, while other compilers implement NULL differently. The new standard fixes this problem with the nullptr keyword. Fix it with a cast:

template <const char* type = static_cast<const char*>(NULL) >

At least, I think that should fix it.

>>error: template declaration of ‘const char* str’

This error is because the way you defined your static const "str" it was interpreted as a declaration of a template static member within the default template-specialization of "asd". That's illegal, and GCC is correct. I have no idea how your Borland compiler interpreted that statement, and why it accepted it.

>>error: template argument 1 is invalid

This error was probably due to the fact that you had no (valid) definition of the static const "str".

The rest of the errors are just consequences of the above errors.


In general, using char-pointer (and almost any other type of pointer) as a template argument is not recommended. The rules for instantiating those templates are a bit circumvented, and you don't want to bother making sure that all template-parameters have external linkage, and all that crap. Just don't use them, most people rarely use them, they can live without them, so you too should be able to. The standard allows it, it doesn't mean you should use it.

>>Except that you made an error in your static constant definition, I'm guessing you meant to write:
template <const char* type>
const char* asd<type>::str = "asd";

I did not.The default template argument should have been deduced when initializing 'str' so there wasn't a need for providing it.The problem is in the declaration where i tried an explicit conversion from NULL to char* but it didn't work.Had there been more errors the borland compiler would have complained or so i think.Consider this:

template <typename T=int> struct dsa  {
   static int x;
 };
template <> int dsa<>::x=10;

template <typename T=int,T a=10> struct qwe  {
   static const int b=12;
 };
typedef qwe<int,qwe<>::b> Qwe;

Since i also got this error:

asd.cpp:14:29: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression

i'll just assume this :

>>This is just a technicality, GCC doesn't seem to want to do integral to pointer casts in a template argument. GCC probably defines NULL as just 0, while other compilers implement NULL differently.

And thank you.

>>I did not.The default template argument should have been deduced when initializing 'str' so there wasn't a need for providing it.

Then, you should have put:

//This is the definition of the str member of the template specialization of asd for its default template-parameter:
template <>
const char* asd<>::str = "asd";

//This is the definition of a "str" template-member for the template specialization of asd for its default template-parameter (which is illegal):
template <const char*>
const char* asd<>::str = "asd";

Using this (the first case), you will still get an error if you use the non-default version of "asd", because the str constant is not defined for the general template.


>>Since i also got this error:

Yeah, I sort-of expected that. Maybe it can work with "nullptr", but Borland won't allow it, so you would need a pre-processor conditional.

This question has already been answered. Start a new discussion instead.