Однако явная перегрузка для соответствующих типов может создавать проблемы при использовании с разными компиляторы используют разные расширенные целочисленные типы [см. здесь].
Однако это похоже на проблему XY. Ваша основная проблема заключается в том, что вы
хотите иметь возможность перегружать типы фиксированной ширины на платформах,
где они отличаются от фундаментальных типов, но не знаете, как
это сделать это не нарушает ваш код на платформах, где они
такие же, как и фундаментальные типы.
Это оказалось проблематичным для меня в Windows 11 [ MSVC, MinGW], Ubuntu 24 [g++] и Petalinux - где
- был расширенным типом в Windows и Petalinux, и
Код: Выделить всё
long - был расширенным типом в Ubuntu.
Код: Выделить всё
long long
Одним дополнительным требованием было не делать функции с необходимыми перегрузками для расширенных целочисленных типов видимыми в файле заголовка, поскольку фактическая реализация довольно тяжелый и поэтому предпочтительно спрятан в cpp-file.
Мое текущее решение в значительной степени опирается на std::enable_if, SFINAE и множество случайных шаблонных кодов. Ниже приводится несколько надуманный, несколько минимальный пример.
templateHelpers.hpp
Код: Выделить всё
#ifndef TEMPLATEHELPERS_HPP
#define TEMPLATEHELPERS_HPP
#include
#include
#include
namespace Custom
{
template
struct UnsignedFixedSized
{
private:
UnsignedFixedSized() = delete;
};
template
struct UnsignedFixedSized
{
typedef uint8_t type;
};
template
struct UnsignedFixedSized
{
typedef uint16_t type;
};
template
struct UnsignedFixedSized
{
typedef uint32_t type;
};
template
struct UnsignedFixedSized
{
typedef uint64_t type;
};
// -----
template
struct UnsignedFixedSameSize
{
typedef typename UnsignedFixedSized::type type;
private:
UnsignedFixedSameSize() = delete;
};
template
struct SignedFixedSized
{
private:
SignedFixedSized() = delete;
};
template
struct SignedFixedSized
{
typedef int8_t type;
};
template
struct SignedFixedSized
{
typedef int16_t type;
};
template
struct SignedFixedSized
{
typedef int32_t type;
};
template
struct SignedFixedSized
{
typedef int64_t type;
};
// -----
template
struct SignedFixedSameSize
{
typedef typename SignedFixedSized::type type;
private:
SignedFixedSameSize() = delete;
};
// -----
template
struct IntegralFixedSameSize_
{
private:
IntegralFixedSameSize_() = delete;
};
template
struct IntegralFixedSameSize_
{
typedef typename SignedFixedSameSize::type type;
};
template
struct IntegralFixedSameSize_
{
typedef typename UnsignedFixedSameSize::type type;
};
template
struct IntegralFixedSameSize
{
typedef typename IntegralFixedSameSize_::type type;
private:
IntegralFixedSameSize() = delete;
};
// -----
template
struct DistinctIntegralNonFixedSizeType
{
static bool constexpr value = !std::is_same_v;
private:
DistinctIntegralNonFixedSizeType() = delete;
};
// -----
template
struct DistinctArithmeticNonFixedSizeOrFloatType_
{
private:
DistinctArithmeticNonFixedSizeOrFloatType_() = delete;
};
template
struct DistinctArithmeticNonFixedSizeOrFloatType_
{
static bool constexpr value = DistinctIntegralNonFixedSizeType::value;
};
template
struct DistinctArithmeticNonFixedSizeOrFloatType_
{
static bool constexpr value = false;
};
template
struct DistinctArithmeticNonFixedSizeOrFloatType
{
static bool constexpr value = DistinctArithmeticNonFixedSizeOrFloatType_::value;
private:
DistinctArithmeticNonFixedSizeOrFloatType() = delete;
};
// -----
} // namespace Custom
#endif // TEMPLATEHELPERS_HPP
Код: Выделить всё
#ifndef STRINGTONUMBER_HPP
#define STRINGTONUMBER_HPP
#include "templateHelpers.hpp"
#include
#include
namespace Custom
{
template const * = nullptr>
T stringToNumber(std::string const & text);
template
T stringToNumber(std::string const & text)
{
return stringToNumber(text);
}
} // namespace Custom
#endif // STRINGTONUMBER_HPP
Код: Выделить всё
#include "stringtonumber.hpp"
#include
#include
#include
#include
#include
namespace // anonymous
{
template
T stringToNumber_(std::string const & text)
{
std::istringstream stream(text);
std::remove_cv_t value = 0;
stream >> value;
if (!stream.eof())
{
throw std::runtime_error(std::string("Failed to decode \"") + text + "\".");
}
return value;
}
} // namespace anonymous
namespace Custom
{
template
uint8_t stringToNumber(std::string const & text)
{
uint16_t const value = stringToNumber_(text);
if (std::numeric_limits::max() < value)
{
throw std::runtime_error(std::string("Failed to decode \"") + text + "\".");
}
return static_cast(value);
}
template
uint16_t stringToNumber(std::string const & text)
{
return stringToNumber_(text);
}
template
uint32_t stringToNumber(std::string const & text)
{
return stringToNumber_(text);
}
template
uint64_t stringToNumber(std::string const & text)
{
return stringToNumber_(text);
}
template
int8_t stringToNumber(std::string const & text)
{
int16_t const value = stringToNumber_(text);
if ((std::numeric_limits::max() < value) || (std::numeric_limits::lowest() > value))
{
throw std::runtime_error(std::string("Failed to decode \"") + text + "\".");
}
return static_cast(value);
}
template
int16_t stringToNumber(std::string const & text)
{
return stringToNumber_(text);
}
template
int32_t stringToNumber(std::string const & text)
{
return stringToNumber_(text);
}
template
int64_t stringToNumber(std::string const & text)
{
return stringToNumber_(text);
}
template
float stringToNumber(std::string const & text)
{
return stringToNumber_(text);
}
template
double stringToNumber(std::string const & text)
{
return stringToNumber_(text);
}
template
long double stringToNumber(std::string const & text)
{
return stringToNumber_(text);
}
} // namespace Custom
Код: Выделить всё
#include
#include "stringtonumber.hpp"
int main()
{
std::cout
Подробнее здесь: [url]https://stackoverflow.com/questions/79270106/is-there-a-more-elegent-way-to-implement-overloads-for-extended-integer-types-wi[/url]
Мобильная версия