research: investigate narrowing conversion problem
as it turns out, this is a Bug in GCC 4.9 (resolved in 5.x) See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63723 Problem is, GCC emits a warning on narrowing conversions, while the standard actually disallows them when building objects from brace-enclosed initialisers. Unfortunately GCC also emits such a warning from within a SFINAE context, instead of letting those spurious dangerous cases fail. So we end up with additional visitor double dispatch paths, and a lot of additional warnings. Temporary solution is to hack a custom trait, which explicitly declares some conversions paths as "narrowing". Probably this can be implemented in a way more intelligent way (using std::numeric_limits), but this doesn't seem worth the effort, since the problem will go away through compiler evolution eventually.
This commit is contained in:
parent
f4bcdcf4e8
commit
1cbebb1fab
2 changed files with 164 additions and 11 deletions
140
research/try.cpp
140
research/try.cpp
|
|
@ -80,12 +80,99 @@ using std::tuple;
|
|||
|
||||
namespace error = lumiera::error;
|
||||
|
||||
//////////////////////////////////////TODO traits
|
||||
namespace lib {
|
||||
namespace meta {
|
||||
using std::is_constructible;
|
||||
using std::is_unsigned;
|
||||
using std::is_signed;
|
||||
using std::is_floating_point;
|
||||
|
||||
|
||||
template<typename NUM>
|
||||
struct is_nonFloat
|
||||
: __and_<is_arithmetic<NUM>
|
||||
,__not_<is_floating_point<NUM>>
|
||||
>
|
||||
{ };
|
||||
|
||||
/** temporary workaround for GCC [Bug-63723], necessary until CGG-5
|
||||
* @remarks The problem is that GCC emits a warning on narrowing conversion,
|
||||
* instead of letting the SFINAE substitution fail. This can be considered
|
||||
* questionable behaviour, since the usual implementation of a `is_convertible`
|
||||
* trait uses initialisation from a brace enclosed list, where C++11 prohibits
|
||||
* narrowing conversions. Now the problem is, that we'll use such traits checks
|
||||
* to remove such _impossble_ cases from generated trampoline tables or visitor
|
||||
* double dispatch implementations. Thus, for one we get lots of warnings at that
|
||||
* point when generating those trampoline tables (at initialisation), while it
|
||||
* is not clear we'll trigger those cases, and, when we do, we'll get narrowing
|
||||
* conversions in a context where we're unable to cope with them or protect
|
||||
* ourselves against spurious conversions.
|
||||
* What follows is a quick-n-dirty hack to remove such unwanted conversions.
|
||||
*
|
||||
* [Bug-63723]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63723
|
||||
*/
|
||||
template<typename SRC, typename TAR>
|
||||
struct is_narrowingInit
|
||||
: __or_<__and_<is_unsigned<SRC>, is_signed<TAR>>
|
||||
,__and_<is_signed<SRC>, is_unsigned<TAR>>
|
||||
,__and_<is_nonFloat<SRC>, is_floating_point<TAR>>
|
||||
,__and_<is_floating_point<SRC>, is_nonFloat<TAR>>
|
||||
,__not_<is_constructible<TAR, SRC>>
|
||||
>
|
||||
{ };
|
||||
|
||||
#define TRAIT_IS_NARROWING(_SRC_, _TAR_) \
|
||||
template<> \
|
||||
struct is_narrowingInit<_SRC_, _TAR_> \
|
||||
: std::true_type \
|
||||
{ };
|
||||
|
||||
TRAIT_IS_NARROWING (int64_t, int32_t)
|
||||
TRAIT_IS_NARROWING (int64_t, int16_t)
|
||||
TRAIT_IS_NARROWING (int64_t, int8_t)
|
||||
TRAIT_IS_NARROWING (int32_t, int16_t)
|
||||
TRAIT_IS_NARROWING (int32_t, int8_t)
|
||||
TRAIT_IS_NARROWING (int16_t, int8_t)
|
||||
TRAIT_IS_NARROWING (int16_t, short)
|
||||
TRAIT_IS_NARROWING (int16_t, char)
|
||||
|
||||
TRAIT_IS_NARROWING (uint64_t, uint32_t)
|
||||
TRAIT_IS_NARROWING (uint64_t, uint16_t)
|
||||
TRAIT_IS_NARROWING (uint64_t, uint8_t)
|
||||
TRAIT_IS_NARROWING (uint32_t, uint16_t)
|
||||
TRAIT_IS_NARROWING (uint32_t, uint8_t)
|
||||
TRAIT_IS_NARROWING (uint16_t, uint8_t)
|
||||
TRAIT_IS_NARROWING (uint16_t, ushort)
|
||||
|
||||
TRAIT_IS_NARROWING (double, float)
|
||||
|
||||
TRAIT_IS_NARROWING (lib::hash::LuidH, int64_t)
|
||||
TRAIT_IS_NARROWING (lib::hash::LuidH, int32_t)
|
||||
TRAIT_IS_NARROWING (lib::hash::LuidH, int16_t)
|
||||
TRAIT_IS_NARROWING (lib::hash::LuidH, int8_t)
|
||||
TRAIT_IS_NARROWING (lib::hash::LuidH, char)
|
||||
TRAIT_IS_NARROWING (lib::hash::LuidH, uint16_t)
|
||||
TRAIT_IS_NARROWING (lib::hash::LuidH, uint8_t)
|
||||
TRAIT_IS_NARROWING (lib::hash::LuidH, double)
|
||||
TRAIT_IS_NARROWING (lib::hash::LuidH, float)
|
||||
|
||||
#undef TRAIT_IS_NARROWING
|
||||
|
||||
}} //////////////////////////////////////TODO traits
|
||||
using std::__not_;
|
||||
using std::__and_;
|
||||
using std::__or_;
|
||||
using std::is_constructible;
|
||||
using lib::meta::is_narrowingInit;
|
||||
using lib::meta::Strip;
|
||||
|
||||
|
||||
using DataCapPredicate = Variant<DataValues>::Predicate;
|
||||
|
||||
|
||||
template<typename TAR>
|
||||
class GenNodeAccessor
|
||||
struct GenNodeAccessor
|
||||
: boost::noncopyable
|
||||
{
|
||||
struct ConverterBase
|
||||
|
|
@ -107,11 +194,16 @@ class GenNodeAccessor
|
|||
};
|
||||
|
||||
template<typename TY>
|
||||
using can_Convert = std::is_constructible<TAR, TY const&>;
|
||||
struct allow_Conversion
|
||||
: __and_<is_constructible<TAR, TY const&>
|
||||
,__not_<is_narrowingInit<typename Strip<TY>::TypePlain
|
||||
,typename Strip<TAR>::TypePlain>>
|
||||
>
|
||||
{ };
|
||||
|
||||
using PossibleSourceTypes = typename Filter<DataValues::List, can_Convert>::List;
|
||||
using SupportedSourceTypes = typename Filter<DataValues::List, allow_Conversion>::List;
|
||||
|
||||
using ConversionBuffer = InstantiateChained< PossibleSourceTypes
|
||||
using ConversionBuffer = InstantiateChained< SupportedSourceTypes
|
||||
, Converter
|
||||
, ConverterBase
|
||||
>;
|
||||
|
|
@ -133,7 +225,7 @@ class GenNodeAccessor
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//////////TODO this goes into typeseq-util.hpp
|
||||
template<class, size_t>
|
||||
struct Pick;
|
||||
|
||||
|
|
@ -221,13 +313,47 @@ buildTuple (SRC values)
|
|||
#define SHOW_TYPE(_TY_) \
|
||||
cout << "typeof( " << STRINGIFY(_TY_) << " )= " << lib::meta::typeStr<_TY_>() <<endl;
|
||||
|
||||
#define EVAL_PREDICATE(_PRED_) \
|
||||
cout << STRINGIFY(_PRED_) << "\t : " << _PRED_ <<endl;
|
||||
|
||||
void
|
||||
verifyConversions()
|
||||
{
|
||||
using std::is_arithmetic;
|
||||
using std::is_floating_point;
|
||||
using lib::meta::is_nonFloat;
|
||||
using lib::hash::LuidH;
|
||||
|
||||
|
||||
EVAL_PREDICATE(is_arithmetic<int> ::value)
|
||||
EVAL_PREDICATE(is_arithmetic<size_t> ::value)
|
||||
EVAL_PREDICATE(is_floating_point<size_t>::value)
|
||||
EVAL_PREDICATE(is_nonFloat<size_t> ::value)
|
||||
|
||||
EVAL_PREDICATE(GenNodeAccessor<int> ::allow_Conversion<size_t> ::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<int64_t>::allow_Conversion<long int>::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<double>::allow_Conversion<int64_t>::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<LuidH>::allow_Conversion<int64_t> ::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<LuidH>::allow_Conversion<int16_t> ::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<LuidH>::allow_Conversion<uint16_t>::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<LuidH> ::allow_Conversion<LuidH> ::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<int64_t> ::allow_Conversion<LuidH>::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<uint64_t>::allow_Conversion<LuidH>::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<uint32_t>::allow_Conversion<LuidH>::value)
|
||||
EVAL_PREDICATE(GenNodeAccessor<int32_t> ::allow_Conversion<LuidH>::value)
|
||||
|
||||
cout <<endl<<endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (int, char**)
|
||||
{
|
||||
using NiceTypes = Types<string, int>;
|
||||
using UgglyTypes = Types<EntryID<long>, string, short, long, float, TimeVar>;
|
||||
verifyConversions();
|
||||
|
||||
using NiceTypes = Types<string, int>;
|
||||
using UgglyTypes = Types<EntryID<long>, string, int, int64_t, double, TimeVar>;
|
||||
|
||||
Rec args = MakeRec().scope("lalü", 42);
|
||||
Rec urgs = MakeRec().scope("lalü", "lala", 12, 34, 5.6, Time(7,8,9));
|
||||
|
|
|
|||
|
|
@ -734,7 +734,7 @@
|
|||
<node CREATED="1453546417098" ID="ID_676713402" MODIFIED="1453546563455" TEXT="DOM vs. compiletime typing">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1453546436455" ID="ID_129001401" MODIFIED="1453546551564" TEXT="double-dispatch">
|
||||
<node CREATED="1453546436455" FOLDED="true" ID="ID_129001401" MODIFIED="1453639145606" TEXT="double-dispatch">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1453546450317" ID="ID_1899026394" MODIFIED="1453590519383" TEXT="Variant-Visitor">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
|
|
@ -749,12 +749,39 @@
|
|||
</node>
|
||||
<node CREATED="1453590522161" ID="ID_1369411965" MODIFIED="1453590545513" TEXT="Problem: narrowing conversions">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#990000" CREATED="1453590566651" ID="ID_1367428687" MODIFIED="1453590610375" TEXT="TODO">
|
||||
<icon BUILTIN="flag"/>
|
||||
</node>
|
||||
<node CREATED="1453590585865" ID="ID_350595711" MODIFIED="1453590606670" TEXT="explizit gefährliche ausschließen">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1453638973049" ID="ID_1350801390" LINK="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63723" MODIFIED="1453639023645">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Compiler-Bug <font color="#c80219">Gcc-#63723</font>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1453639033250" ID="ID_1669831951" LINK="http://stackoverflow.com/questions/26705199/how-can-i-write-a-type-trait-to-check-if-a-type-is-convertible-to-another-by-a-n" MODIFIED="1453639049952" TEXT="s.a. Stackoverflow"/>
|
||||
<node CREATED="1453639055478" ID="ID_1560466275" MODIFIED="1453639078468">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
gelöst in GCC-5 -- <i>backport unwahrscheinlich</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1453639119142" ID="ID_1472487058" MODIFIED="1453639126177" TEXT="inzwischen hartgecodet">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1453546467707" ID="ID_1543497504" MODIFIED="1453546472446" TEXT="Problem: template bloat">
|
||||
<node CREATED="1453590622236" ID="ID_1084684065" MODIFIED="1453590761460" TEXT="hält sich in Grenzen">
|
||||
|
|
|
|||
Loading…
Reference in a new issue