-1
    #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);
    }

template specialization for Cls fails (case 1, case 2) if the function argument is const ref but by val works for all cases.

Is there any way other than pass by valto handle specialization for all cases (all value types)?

Praveen
  • 8,945
  • 4
  • 31
  • 49

2 Answers2

1

You could solve this issue using SFINAE, but it would be much easier to get rid of the overload on _struct and define an overload for operator<<:

std::ostream& operator<<(std::ostream& os, const _struct& obj)
{
  os << obj.dval;
  return os;
}

A possibility for solving with SFINAE would be to check for the validity of outputting Obj directly in one overload and check the type against _struct in the other:

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;
} 
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • 1
    This is [expression SFINAE](http://stackoverflow.com/questions/12654067/what-is-expression-sfinae). Essentially, if the expression in that decltype is ill-formed, that overload is purged from the candidate set rather than resulting in a hard error. – TartanLlama Apr 21 '15 at 10:19
0

You need a helper struct:

#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");
}
WaeCo
  • 1,155
  • 1
  • 10
  • 21