C++ 中的函数模板特化和右值引用

Function template specialization and rvalue reference in c++

    #include <iostream>

    struct Cls{double dval = 0;};

    template<typename T>
    void foo(T&& Obj) {
        //..... use Obj
    } 

    void foo(const Cls& Obj) {
        //..... use Obj.dval
    }

    //void foo(Cls Obj) {
    //    //..... use Obj.dval
    //}

    int main()
    {
        Cls Obj;
        const Cls cv_Obj;

        foo(Obj); //case 1
        foo(Cls{}); //case 2
        foo(cv_Obj); //case 3
        foo(10.10);
    }

如果函数参数是 const refCls 的模板特化失败 (case 1, case 2),但 by val 适用于所有情况。

除了 pass by val 之外,还有其他方法可以处理所有 cases(所有值类型)的专业化吗?

您可以使用 SFINAE 解决此问题,但摆脱 _struct 上的重载并为 operator<<:

定义重载会容易得多
std::ostream& operator<<(std::ostream& os, const _struct& obj)
{
  os << obj.dval;
  return os;
}

用 SFINAE 解决的一种可能性是在一个重载中直接检查输出 Obj 的有效性,并在另一个重载中检查 _struct 的类型:

template<typename T>
auto foo(T&& Obj) -> decltype(std::cout<<Obj, void()) {
    std::cout<<Obj;
}

template<typename T, 
         std::enable_if_t<std::is_same<_struct, std::decay_t<T>>::value>* = nullptr>
void foo(T&& Obj) {
    std::cout<<Obj.dval;
} 

你需要一个辅助结构:

#include <iostream>

struct _struct{double dval = 0;};

template<typename T, typename Enable = void>
struct bar {
    bar(T&& Obj) {
        std::cout<<Obj;
    }
};

template<typename T>
struct bar<T, typename std::enable_if<std::is_same<typename std::decay<T>::type, _struct>::value>::type> {
    bar(T&& Obj) {
        std::cout<<Obj.dval;
    }
};

template<typename T>
void foo(T&& Obj) {
    bar<T>(std::forward<T>(Obj));
}

int main()
{
    _struct Obj;
    const _struct cv_Obj;

    foo(1);
    foo(Obj); //case 1
    foo(_struct{}); //case 2
    foo(cv_Obj); //case 3
    foo("test");
}