如何使用类型特征来比较具有多个参数的类中的第一个模板参数?

How can I use type traits to compare only the first template parameter in class that has multiple parameters?

本文关键字:参数 第一个 特征 类型 何使用 比较      更新时间:2023-10-16

我有这个函数GetProperty(),它的定义如下:

template<typename T>
void GetProperty(T & val)

我想让它接受三个可能的值:bool, int,和一个有两个模板参数的字符串类。字符串类,我们称之为StringT,看起来像这样:

template<typename CharType, size_t Size>
class StringT

我希望能够将StringT的实例传递给GetProperty(),以便它只检查CharType并允许Size的任何值。例如,这两个调用都应该在没有任何额外专门化的情况下工作:

StringT<char, 512> str1;
GetProperty(str1);
StringT<char, 1024> str2;
GetProperty(str2);

当前的实现是这样的:

template<typename T>
void GetProperty(T & val)
{
    // Trying to use static_assert to only allow StringT values in the default implementation.
    static_assert(std::is_same<T, StringT<char, 512>>::value, "FAILED");
    // Do stuff
}
template<>
void GetProperty<bool>(bool & val)
{
    // Do stuff
}
template<>
void GetProperty<int>(int & val)
{
    // Do stuff
}

显然这不起作用,因为它只允许指定StringT<char, 512>类型。是否有任何方法可以忽略512模板参数并让它接受Size的任何值?

选项#1

为每个类型提供单独的函数重载,这样您就可以在一个重载中接受任何StringT<char, ?>:

template <size_t N>
void GetProperty(StringT<char, N>& val) {}
void GetProperty(bool val) {}
void GetProperty(int val) {}

演示1

选项# 2

写你自己的type-trait:

#include <type_traits>
template <typename S, typename C>
struct IsStringT : std::false_type {};
template <typename C, size_t Size>
struct IsStringT<StringT<C, Size>, C> : std::true_type {};
template <typename T>
void GetProperty(T & val)
{
    static_assert(IsStringT<typename std::remove_cv<T>::type, char>{}, "FAILED");
}
template <>
void GetProperty<bool>(bool & val) {}
template <>
void GetProperty<int>(int & val) {}

演示2

如果您可以控制StringT类,则可以在公共部分添加额外的字段,其效果为:

using char_t = CharType;

那么你可以将你的静态断言更新为:

static_assert(std::is_same<typename T::char_t, char>::value, "FAILED");

在这种情况下,任何定义了char_t的类都可以在这里使用。

另一方面,如果你知道GetProperty总是与StringT一起使用,你可以将它的最外层定义更改为:
template<typename CharType, size_t Size>
void GetProperty(StringT<CharType,Size> & val)

…然后你可以直接访问CharType .