【问题标题】:Specializing method template while checking for subtype在检查子类型时专门化方法模板
【发布时间】:2018-09-28 06:21:34
【问题描述】:

在检查某个子类型是否存在的同时,为方法专门化模板的语法是什么?

// Syntax works fine for functions
template<class T, class... Assertions> void my_function();

template <class list_t, class list_t::value_type>
void my_function() { }

// Doesn't work for methods
class MyClass {
    template<class T, class... Assertions> void my_method();
};

// Commenting out the next two lines results in successful compile
template <class list_t, class list_t::value_type>
void MyClass::my_method() { }

int main() { }

Clang 给了我:

out-of-line definition of 'my_method' does not match any declaration in 'MyClass'

【问题讨论】:

    标签: c++ templates variadic-templates sfinae template-specialization


    【解决方案1】:

    您在这里既不专门化模板方法也不专门化函数。您只是在重载免费模板函数并试图以一种奇怪的方式重载该方法。为了使它工作你应该使用标签调度(因为部分函数模板在 C++ 中是不可能的)或constexpr if 如果你的编译器支持 C++17

    【讨论】:

    • 如何检查子类型是否存在?
    【解决方案2】:

    特化语法如下:

    // dummy list_t...
    struct list_t
    {
       using value_type = int;
    };
    
    // standard implementation:
    template<class T, class... Assertions>
    void my_function() { }
    
    // specialization
    template <>
    void my_function<list_t, list_t::value_type>() { }
    
    class MyClass
    {
        template<class T, class... Assertions>
        void my_method();
    };
    
    // standard implementation:
    template<class T, class... Assertions>
    void MyClass::my_method() { }
    
    // specialisation
    template <>
    void MyClass::my_method<list_t, list_t::value_type>() { }
    

    【讨论】:

    • list_t 应该是具有::value_type 的泛型类型;不是具体类型。
    • 这样的:template &lt;class list_t, class VT = typename list_t::value_type&gt; void my_function() { }
    • out-of-line definition of 'my_method' does not match any declaration in 'MyClass'
    • 请注意,您不能在 C++ 中部分特化函数!但是,如果使用上述方法,您可能会产生模棱两可的重载。
    • 本身是模板吗?
    【解决方案3】:

    我不清楚你到底想要什么。

    如果您希望 my_method() 仅在 T 是其中包含 value_type 类型的类/结构时实现,并且您希望在使用 T 而没有 value_type 调用时出现编译错误它,我建议通过declval()decltype()使用SFINAE。

    某事

    template <typename T>
    auto my_method ()
       -> decltype( std::declval<typename T::value_type>(), void() )
     { }
    

    如果可以使用 C++17,而不是 decltype( std::declval&lt;typename T::value_type&gt;(), void() ),则可以使用 std::void_t&lt;T::value_type&gt;

    如果您想要一个具有更通用版本的my_method() 和一个带有value_type 的类/结构的专用版本,我建议开发一个通用my_method(),它只需调用另一个方法my_method_helper() 添加int

    template <typename T>
    void my_method ()
     { my_method_helper<T>(0); }
    

    并将my_method_helper() 的 SFINAE 和函数重载与接收 long(所以不完全是 int)的 my_method_helper() 相结合,并且已为更通用的版本启用

    template <typename T>
    void my_method_helper (long)
     { }
    

    以及恰好接收int 的版本(因此,如果可用,则优先于long 版本)但仅当T 包含value_type 时才启用。

    template <typename T>
    auto my_method_helper (int)
       -> decltype( std::declval<typename T::value_type>(), void() )
     { }
    

    所以当T 包含value_type 时调用my_method_helper(int),否则调用my_method_helper(long)

    以下是一个完整的编译示例(方法名已更改)

    #include <utility>
    #include <iostream>
    
    struct MyClass
     {
       template <typename T>
       auto method_1 ()
          -> decltype( std::declval<typename T::value_type>(), void() )
        { std::cout << "method_1 " << std::endl; }
    
       template <typename T>
       auto method_2 (int)
          -> decltype( std::declval<typename T::value_type>(), void() )
        { std::cout << "method_2 specialized" << std::endl; }
    
       template <typename T>
       void method_2 (long)
        { std::cout << "method_2 generic" << std::endl; }
    
       template <typename T>
       void method_2 ()
        { method_2<T>(0); }
     };
    
    struct foo
     { using value_type = int; };
    
    int main()
     {
       MyClass mc;
    
       mc.method_1<foo>();
       // mc.method_1<int>(); // compilation error
    
       mc.method_2<foo>(); // call specialized version
       mc.method_2<int>(); // call generic version
     }
    

    部分偏离主题:我不明白“语法适用于函数”是什么意思

    template<class T, class... Assertions> void my_function();
    
    template <class list_t, class list_t::value_type>
    void my_function() { }
    

    你怎么称呼my_function()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 2015-06-15
      • 1970-01-01
      • 2014-02-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多