Есть ли более элегантный способ реализовать перегрузки расширенных целочисленных типов со скрытыми шаблонами в C++?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Есть ли более элегантный способ реализовать перегрузки расширенных целочисленных типов со скрытыми шаблонами в C++?

Сообщение Anonymous »

Как уже обсуждался этот вопрос, расширенный целочисленный тип не перехватывается функциями, которые для них не перегружены явно.
Однако явная перегрузка для соответствующих типов может создавать проблемы при использовании с разными компиляторы используют разные расширенные целочисленные типы [см. здесь].

Однако это похоже на проблему XY. Ваша основная проблема заключается в том, что вы
хотите иметь возможность перегружать типы фиксированной ширины на платформах,
где они отличаются от фундаментальных типов, но не знаете, как
это сделать это не нарушает ваш код на платформах, где они
такие же, как и фундаментальные типы.

Это оказалось проблематичным для меня в Windows 11 [ MSVC, MinGW], Ubuntu 24 [g++] и Petalinux - где Поэтому было невозможно отличить его с помощью - по общему признанию несвязанного - определения препроцессора #ifdef WIN32 и #ifdef UNIX.
Одним дополнительным требованием было не делать функции с необходимыми перегрузками для расширенных целочисленных типов видимыми в файле заголовка, поскольку фактическая реализация довольно тяжелый и поэтому предпочтительно спрятан в 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
stringtonumber.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
stringtonumber.cpp

Код: Выделить всё

#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
main.cpp

Код: Выделить всё

#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]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»