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

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

所以我有这个函数,GetProperty(),定义如下:

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

我希望它接受三个可能的值:boolint 和具有两个模板参数的字符串 class。字符串 class,我们称它为 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) {}

DEMO 1

选项#2

写下你自己的类型特征:

#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) {}

DEMO 2

如果您可以控制 StringT class,您可以在 public 部分添加一个额外的字段,效果如下:

using char_t = CharType;

然后您可以将静态断言更新为:

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

在这种情况下,可以在此处使用定义了 char_t 的任何 class。

另一方面,如果您知道 GetProperty 将始终与 StringT 一起使用,您可以将其最外层定义更改为:

template<typename CharType, size_t Size>
void GetProperty(StringT<CharType,Size> & val)

...然后您将可以直接访问 CharType