代码之家  ›  专栏  ›  技术社区  ›  Justin G

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

  •  2
  • Justin G  · 技术社区  · 10 年前

    所以我有这个功能, GetProperty() ,定义如下:

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

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

    template<typename CharType, size_t Size>
    class StringT
    

    我希望能够通过 字符串T 获取属性() 所以它只检查 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 模板参数,并使其接受 大小 ?

    2 回复  |  直到 10 年前
        1
  •  2
  •   Piotr Skotnicki    10 年前

    选项#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

        2
  •  0
  •   Piotr Skotnicki    10 年前

    如果您可以控制 StringT 类,您可以向公共部分添加一个额外的字段,效果如下:

    using char_t = CharType;
    

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

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

    在本例中,任何具有 char_t 此处可以使用defined。

    另一方面,如果你知道 GetProperty 将始终与 字符串T ,可以将其最外层定义更改为:

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

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