Следующий код делает все, что мне нужно, в каждом C ++ 11 и более поздних компиляторах, которые я пробовал. Таким образом, на практике для моих целей это работает (и, как ожидается, будет работать, по крайней мере, в Linux, в обозримом будущем по историческим причинам). Однако с точки зрения юриста языка этот код недопустим, поскольку он содержит конструкцию (разыменование указателя на несуществующий объект), которая формально является UD, даже если эта разыменование фактически никогда не выполняется.
#include <type_traits>
#include <iostream>
namespace n1 {
struct int_based { int base = 0; };
inline int get_base(int_based ib) { return ib.base; }
}
namespace n2 {
struct double_based;
double get_base(const double_based&);
}
template <typename T>
using base_type = decltype((get_base(*(T*)nullptr)));
int main() {
auto isInt = std::is_same<base_type<n1::int_based>, int>::value;
auto isDouble = std::is_same<base_type<n2::double_based>, double>::value;
auto unlike = std::is_same<base_type<n1::int_based>, double>::value;
std::cout << isInt << isDouble << unlike << std::endl;
return 0;
}
Код выполняет поиск Кенига для сопоставления типов и выводит сопоставленный тип, используя сигнатуры функций, которые я не хотел бы изменять. В этом примере тип double_based
является неполным;в моих реальных случаях использования типы должны быть завершены, но не гарантировано, что они будут DefaultConstructible
. Фактический код является частью логики безопасной сериализации.
Вопрос заключается в следующем: существует ли стандартизированный способ "материализации" объекта типа параметра шаблона T
для использования в * 1009? * в этом коде, или невозможно иметь такое соответствие стандарту соответствия типов без предварительно созданного объекта типа источника?
Замена параметров функции указателями на объекты является уродливой и не решаетпроблема, так как неясно, что эти функции должны делать с аргументом nullptr
в общем случае, не вводя еще один UB.