Да, проверьте значения констант типов float
и double
, например: float.PositiveInfinity
float.NegativeInfinity
Эти значения соответствуют IEEE -754, так что вы можете проверить, как это работает точно, чтобы вы знали, когда и как вы можете получить эти значения при выполнении расчетов. Более подробная информация здесь .
Ответ Алексея Малистова можно использовать в MSVC с небольшими изменениями:
namespace
{
template<class T, int discriminator>
struct is_complete {
static T & getT();
static char (& pass(T))[2];
static char pass(...);
static const bool value = sizeof(pass(getT()))==2;
};
}
#define IS_COMPLETE(X) is_complete<X,__COUNTER__>::value
К сожалению, предопределенный макрос __ COUNTER __
не является частью стандарта, поэтому он не будет работать на всех компиляторах.
template<class T>
struct is_complete {
static T & getT();
static char (& pass(T))[2];
static char pass(...);
static const bool value = sizeof(pass(getT()))==2;
};
Я не могу найти в стандарте ничего, что гарантировало бы, что sizeof для неполного типа вернет 0. Однако он требует, чтобы если T в какой-то момент был неполным, но завершился позже в эта единица перевода, что все ссылки на T относятся к одному и тому же типу - так что, как я читал, даже если T неполный там, где был вызван ваш шаблон, нужно было бы сказать, что он был завершен, если T завершен где-то в этом переводе ед.
Боюсь, что вы не сможете реализовать такие is_complete
типовые признаки. Реализация, данная @Alexey, не компилируется на G++ 4.4.2 и G++ 4.5.0:
ошибка: инициализирующий аргумент 1 'static char (& is_complete::pass(T))[2] [с T = Foo]'
На моем Mac, с G++ 4.0. 1 вычисляющий is_complete
, где struct Foo;
является неполными значениями для true
, что еще хуже ошибки компилятора.
T
может быть как полным, так и неполным в одной и той же программе, в зависимости от единицы трансляции, но это всегда один и тот же тип. Как следствие, как было прокомментировано выше, is_complete
тоже всегда один и тот же тип.
Так что если вы уважаете is_completeis_complete
вычислял разные значения в зависимости от того, где он используется; в противном случае это означало бы, что у вас разные определения для is_complete
, которые запрещены в рамках УСО.
EDIT: Как принятый ответ, я сам взломал решение, которое использует макрос __COUNTER__
, чтобы инстанцировать другой тип is_complete
каждый раз, когда используется макрос IS_COMPLETE
. Однако с gcc я не смог заставить SFINAE работать в первую очередь.