Back to Programming techniques
This section contains some differences in compilers. These differences cause code compiling on one platform to not compile on another platform. Since I run to these problems constantly, I will document them here.
The gcc 4.8
‘s C++ Standard Library does not support C++14 fully. For example, it does not implement alias templates for type-traits, such as std::make_unsigned_t
.
Option 1: Update the compiler; gcc 4.9
has improved support for C++14.
Option 2: Replace the unsupported stuff with supported stuff, as in typename std::make_unsigned<T>::type
.
In gcc
and Clang
, declaring a type Type
in a class template with a template parameter Type
produces an error about shadowing a type.
Our actual use-case is to store the template-argument into the class. In this case the ambiguity does not matter:
template <typename Type>
struct C
{
using Type = Type;
};
However, it is good that the error is emitted because of code such as this:
template <typename Type>
struct C
{
using Type = int;
};
Use a trailing underscore for template parameters to avoid the ambiguity.
template <typename Type_>
struct C
{
using Type = Type_;
};
The following fails to compile in gcc
and Clang
, but compiles in Visual Studio 2013:
class C;
namespace N
{
class A
{
private:
friend class C;
A() {}
};
}
class C
{
public:
C()
{
N::A a;
}
};
int main()
{
C c;
return 0;
}
By the standard, the code should not compile, since here friend class C;
is equivalent to friend class N::C
. The problem is that Visual Studio allows the friend declaration to find the referred class from a parent namespace, which may suggest that this is the standard behaviour.
Replace friend class C;
with friend class ::C
. When the namespace is not specified, the friend class is assumed to be in the enclosing namespace, that is, N
.
The following fails to compile in gcc
and Clang
, but compiles in Visual Studio 2013:
class A {};
class B
: public A
{
};
class C
: public A
, public B
{
public:
A& f()
{
return *this;
}
};
int main()
{
C c;
c.f();
return 0;
}
The problem is that it is ambiguous which base-class A
is meant. I thought that this should resolve to the direct base-class A
. I don’t know what the standard says.
To disambiguate to B::A
, replace return *this;
with return (B&)*this;
. I don’t know how to disambiguate to C::A
.