如何使用类型特征仅比较 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)
我希望它接受三个可能的值:bool
、int
和具有两个模板参数的字符串 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) {}
选项#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) {}
如果您可以控制 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
。
所以我有这个函数,GetProperty()
,定义如下:
template<typename T>
void GetProperty(T & val)
我希望它接受三个可能的值:bool
、int
和具有两个模板参数的字符串 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) {}
选项#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) {}
如果您可以控制 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
。