Nik*_*o O 3 c++ templates c++17
template<typename T> void frobnicate()我有一个可以做事的函数。我需要 T 成为几种选择类型之一,并且我需要有关这些类型的一些信息。我通过提供特征来做到这一点:
template<typename T_Raw>
struct FrobnicationTraits
{
static constexpr bool isValidFrobnicationType = false;
};
template<>
struct FrobnicationTraits<unsigned char>
{
static constexpr bool isValidFrobnicationType = true;
static constexpr bool isUnsigned = true;
static constexpr unsigned char minValue = 0;
static constexpr unsigned char maxValue = 255;
//Elided in each specialization: some other values that are needed by frobnicate()
};
template<>
struct FrobnicationTraits<signed char>
{
static constexpr bool isValidFrobnicationType = true;
static constexpr bool isUnsigned = false;
static constexpr signed char minValue = -128;
static constexpr signed char maxValue = 127;
};
//Elided: versions for unsigned short and signed short
Run Code Online (Sandbox Code Playgroud)
进而:
template<typename T, typename = typename std::enable_if<FrobnicationTraits<T>::isValidFrobnicationType>::type>
void frobnicate()
{
using Traits = FrobnicationTraits<T>;
auto promotedMinValue = +Traits::minValue;
auto promotedMaxValue = +Traits::maxValue;
std::cout << "Frobnicating with " << (Traits::isUnsigned ? "unsigned" : " signed") << " type of size " << sizeof(T) <<" between " << promotedMinValue << " and " << promotedMaxValue << std::endl;
//...
}
Run Code Online (Sandbox Code Playgroud)
这对于这些调用来说效果很好:
int main()
{
frobnicate<unsigned char>(); // Prints "Frobnicating with unsigned type of size 1 between 0 and 255"
frobnicate< signed char>(); // Prints "Frobnicating with signed type of size 1 between -128 and 127"
frobnicate<unsigned short>(); // Prints "Frobnicating with unsigned type of size 2 between 0 and 65535"
frobnicate< signed short>(); // Prints "Frobnicating with signed type of size 2 between -32768 and 32767"
//frobnicate<unsigned int>(); // Correctly fails to compile, because the enable_if is not satisfied, since FrobnicationTraits<unsigned int> uses the default FrobnicationTraits where isValidFrobnicationType is false
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但现在我希望能够正确frobnicate<char>()。
char是实现定义为有符号或无符号的,但它始终被认为是与unsigned char和不同的类型signed char。因此,简单地调用frobnicate<char>()无法编译,因为它不会选择任何专门的 FrobnicationTraits。
我可以手动添加一项专业:
template<>
struct FrobnicationTraits<char>
{
static constexpr bool isValidFrobnicationType = true;
static constexpr bool isUnsigned = true;
static constexpr char minValue = 0;
static constexpr char maxValue = 255;
};
Run Code Online (Sandbox Code Playgroud)
但我无法提前知道这是否正确。事实上,我碰巧选择了错误的值,所以这会打印“Frobnicating with unsigned type of size 1 between 0 and -1”。
我想有效地做到这一点:
template<> // I don't know where to put the `std::enable_if<>` here, but use this if char is unsigned
struct FrobnicationTraits<char>
{
static constexpr bool isValidFrobnicationType = true;
static constexpr bool isUnsigned = true;
static constexpr char minValue = 0;
static constexpr char maxValue = 255;
};
template<> // I don't know where to put the `std::enable_if<>` here, but use this if char is signed
struct FrobnicationTraits<char>
{
static constexpr bool isValidFrobnicationType = true;
static constexpr bool isUnsigned = false;
static constexpr char minValue = -128;
static constexpr char maxValue = 127;
};
Run Code Online (Sandbox Code Playgroud)
理想情况下,解决方案不应使用预处理器。
有一个std::is_signed可以告诉你是否char签名。如果您不需要区分char和signed char/,您可以通过std::conditionalunsigned char继承其中一个来重用这些特征:
template<>
struct FrobnicationTraits<char> : FrobnicationTraits<
std::conditional_t<
std::is_signed_v<char>,
signed char,
unsigned char
>
>
{};
Run Code Online (Sandbox Code Playgroud)
也许使用一个助手:
using signed_or_unsigned_char = std::conditional_t<std::is_signed_v<char>,signed char, unsigned char>;
Run Code Online (Sandbox Code Playgroud)
然后继承FrobnicationTraits<char>自FrobnicationTraits<signed_or_unsigned_char>.
PS:请注意,您的一些特征功能已经包含在std::numerical_limits. 如果直接使用std::is_signed,则特征中实际需要的只是isValidFrobnicationType.
| 归档时间: |
|
| 查看次数: |
94 次 |
| 最近记录: |