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.