A user has reported being unable to compile Simutrans-Extended with GCC 10. The reported error is:
bauer/../dataobj/livery_scheme.h:28:23:
/usr/include/c++/10.1.0/type_traits:960:52: Error: template argument
must be a complete class or an unbounded array
960 |
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
I have not been able to find any intelligible explanation of how this error might arise in the web page concerned with porting from GCC 9 to GCC 10 (https://gcc.gnu.org/gcc-10/porting_to.html).
The relevant line on which compilation fails is:
vector_tpl<livery_t> liveries;
"livery_t" is a struct defined as:
struct livery_t
{
std::string name;
uint16 intro_date;
};
The relevant include is present in the header file:
#include <string>
I am afraid that I do not understand this error at all and have not been able to find any intelligible information at all on the error, "Error: template argument must be a complete class or an unbounded array" so as to try to work out what the problem might be.
I should be grateful for any assistance from anyone with any understanding of GCC 10, what this error is and how it might arise.
std namespace woes again ... GCC tries to use std::swap instead of the swap defined in vector_tpl.h. IMO the "using namespace std" should really be removed sooner than later to avoid issues like this. Anyway, the compile error should be fixed by #181 (https://github.com/jamespetts/simutrans-extended/pull/181).
Thank you for that - that is extremely helpful. This is now incorporated.
As to removing "using namespace std", I do not know how one might go about this without breaking anything else.
remove it and explicitly prefix calls to STL functions by "std::".
e.g. instead of
using namespace std;
...
min(1,2);
use
sdt::min(1,2)
With min/max, the complexity is that there are actually bespoke Simutrans functions for these, albeit they do not work properly for 64-bit variables.
Yes, so use std::min and std::max to use the functions from STL and simply min or max to use the (non namespaced) simutrans functions.
In both cases the headers need to be included for sure.
Quote from: Freahk on May 25, 2020, 04:09:18 PM
Yes, so use std::min and std::max to use the functions from STL and simply min or max to use the non namespaced) simutrans functions.
Both assume the headers are included for sure.
I am not sure why we want to use the simutrans implementation of such STL functions anyways.
This is a legacy from Standard - I am not sure whether any of the Standard developers know the basis for this or whether there is any reason for retaining this?
Exactly, I'd expect it to exist for legacy reasons.
C++ stdlib was first introduced in C++98, where simutrans started in 1997?
I have no idea when C++98 was first introduced to simutrans.
Many of simutrans stdlib duplicates seem to be quite old, so I'd expect these to exist because the std variant was simply not available to simutrans at that time and nobody refactored the code later on.
Don't get me wrong, I'm not saying we should refactor the whole code, but imho stdlib features should be used for new code or when doing changes in the code anyway.
IMO the std::min/max should completely replace the dangerous Simutrans defined ones. Far too easy for "bad things" happening with them (compiler silently passing uint32 as sint32 and....)
I'd started to do so after falling into that trap one too many times, but as usual never finished - probably useless now patch attached, it's for standard and 3 years old. Never finished verifying the explicit types. [you can't just change max() to std::max() as the compiler is too dumb to deduce the type quite often. e.g. need std::max<uint32>()]
Quote from: TurfIt on May 25, 2020, 06:31:12 PM[you can't just change max() to std::max() as the compiler is too dumb to deduce the type quite often. e.g. need std::max<uint32>()]
An improvement might be something like this which allows comparing types of same signedness, but not mixed:
namespace sim {
template<typename T1, typename T2, typename R = typename std::enable_if<std::is_signed<T1>::value == std::is_signed<T2>::value, typename std::common_type<T1, T2>::type>>
R min(const T1 &a, const T2 &b)
{
return a < b ? a : b;
}
}
Requires C++11, so it's not for Standard.