代码之家  ›  专栏  ›  技术社区  ›  Afshin

当方法可用时,如何专门化模板?

  •  3
  • Afshin  · 技术社区  · 3 年前

    我想知道当我的类型有一个特定的方法时,我如何能有一个专门的模板。让我们以以下代码为例:

    template<typename T, typename... Args>
    void foo(T&& arg, Args&&... args) {
        std::cout << "called 1\n";
    }
    
    template<typename T, std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::log)>, int> = 0>
    void foo(T&& v) {
        v.log();
    }
    
    struct Y {
        void log() const {
            std::cout << "called 2\n";
        }
    };
    
    int main() {
        foo(1); // <-- print "called 1";
        Y y;
        foo(y); // <-- print "called 2";
    }
    

    我应该说这个代码不起作用(第二) foo called 1 )我知道我不能部分地专门化函数调用,但它显示了我所需要的。

    你知道我怎样才能做到这一点吗?我应该使用结构来部分专门化,然后使用辅助函数吗?

    2 回复  |  直到 3 年前
        1
  •  3
  •   Jarod42    3 年前

    你的情况很好,但是,有了转发参考,

    decltype(&T::log) 变成 decltype(&(Y&)::log) 这是无效的。

    std::decay 解决您的问题:

    template <typename T,
              std::enable_if_t<
                  ​std::is_member_function_v<decltype(&std::decay_t<T>::log)>,
                  int> = 0>
    void foo(T&& v)
    { 
       ​v.log();
    }
    

    Demo

        2
  •  3
  •   JeJo    3 年前

    你不需要那么冗长;您可以启用另一个 foo

    template<typename T>
    auto foo(T&& v) -> decltype(v.log(), void())  
    {
        v.log();
    }
    

    See a Demo )

    trailing return type . 你提供 decltype 要计算表达式(1)。 v.log() void() )与 comma operator 分离。如果第一个表达式(即。 v、 日志() void void() 表情!