function template does not recognize lvalue - c++

I have a problem in my code
Here is simplified version of it :
#include <iostream>
class A
{
public :
template <class T>
void func(T&&)//accept rvalue
{
std::cout<<"in rvalue\n";
}
template <class T>
void func(const T&)//accept lvalue
{
std::cout<<"in lvalue\n";
}
};
int main()
{
A a;
double n=3;
a.func(n);
a.func(5);
}
I expect the output to be :
in lvalue
in rvalue
but it is
in rvalue
in rvalue
why ?!

template <class T> void func(T&&) is universal reference forwarding reference.
To test what you want, try: (Live example)
template <typename T>
class A
{
public:
void func(T&&)//accept rvalue
{
std::cout<<"in rvalue\n";
}
void func(T&)//accept lvalue
{
std::cout<<"in lvalue\n";
}
};
int main()
{
A<double> a;
double n = 3;
a.func(n);
a.func(5.);
}

To build on Jarod42's fine answer, if you want to keep the design of having a primary function template, you can decide based on the deduced type of the universal reference parameter:
#include <iostream>
#include <type_traits>
struct A
{
template <typename T> // T is either U or U &
void func(T && x)
{
func_impl<T>(std::forward<T>(x));
}
template <typename U>
void func_impl(typename std::remove_reference<U>::type & u)
{
std::cout << "lvalue\n";
}
template <typename U>
void func_impl(typename std::remove_reference<U>::type && u)
{
std::cout << "rvalue\n";
}
};

I think the surprise comes from the way the template argument are deduced. You'll get what you expect if you write:
a.func<double>(n);

Related

disable code from compiling for non integral types [duplicate]

This question already has answers here:
Template Function Specialization for Integer Types
(6 answers)
Closed last year.
#include <iostream>
#include <type_traits>
#include <math.h>
template<typename T>
void Foo(T x)
{
if(std::is_integral<T>::value)
{
rint(x);
}
else
{
std::cout<<"not integral"<<std::endl;
}
}
int main()
{
Foo("foo");
return 0;
}
Does not compile because there is no suitable rint overload for const char*, but rint will never be invoked with const char* because it's not an integral type. How can I inform the compiler about this
One way would be to use std::enable_if as shown below:
template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type Foo(T x)
{
std::cout<<"Foo called for integral type"<<std::endl;
rint(x);
}
template<typename T>
typename std::enable_if<!std::is_integral<T>::value>::type Foo(T x)
{
std::cout<<"non-integral type"<<std::endl;
}
int main()
{
Foo(5);// calls Foo integral type
Foo('c'); //calls Foo for integral type
Foo("c"); //call Foo for non-integral type
return 0;
}
In c++17 you could use if constexpr instead of if and it would work.
In c++14 you could specialize a struct to do what you want
template<class T, bool IsIntegral = std::is_integral<T>::value>
struct do_action
{
void operator()(T val) { rint(val); }
};
template<class T>
struct do_action<T, false>
{
void operator()(T val) { std::cout << "Not integral\n"; }
};
template<class T>
void Foo(T x)
{
do_action<T>()(x);
}

Execute function inside function template only for those types that have the function defined

I have a function template which takes many different types as it's input. Out of those types only one of them has a getInt() function. Hence I want the code to run the function only for that type. Please suggest a solution. Thanks
#include <type_traits>
#include <typeinfo>
class X {
public:
int getInt(){
return 9;
}
};
class Y{
};
template<typename T>
void f(T& v){
// error: 'class Y' has no member named 'getInt'
// also tried std::is_same<T, X>::value
if(typeid(T).name() == typeid(X).name()){
int i = v.getInt();// I want this to be called for X only
}
}
int main(){
Y y;
f(y);
}
If you want to be able to call a function f for all types that have function member getInt, not just X, you can declare 2 overloads for function f:
for types that have getInt member function, including class X
for all the other types, including class Y.
C++11 / C++17 solution
Having that in mind, you could do something like this:
#include <iostream>
#include <type_traits>
template <typename, typename = void>
struct has_getInt : std::false_type {};
template <typename T>
struct has_getInt<T, std::void_t<decltype(((T*)nullptr)->getInt())>> : std::is_convertible<decltype(((T*)nullptr)->getInt()), int>
{};
class X {
public:
int getInt(){
return 9;
}
};
class Y {};
template <typename T,
typename std::enable_if<!has_getInt<T>::value, T>::type* = nullptr>
void f(T& v) {
// only for Y
std::cout << "Y" << std::endl;
}
template <typename T,
typename std::enable_if<has_getInt<T>::value, T>::type* = nullptr>
void f(T& v){
// only for X
int i = v.getInt();
std::cout << "X" << std::endl;
}
int main() {
X x;
f(x);
Y y;
f(y);
}
Check it out live.
Please note that std::void_t is introduced in C++17, but if you are limited to C++11, then it is really easy to implement void_t on your own:
template <typename...>
using void_t = void;
And here is C++11 version live.
What do we have in C++20?
C++20 brings lots of good things and one of them is concepts. Above thing that's valid for C++11/C++14/C++17 can be significantly reduced in C++20:
#include <iostream>
#include <concepts>
template<typename T>
concept HasGetInt = requires (T& v) { { v.getInt() } -> std::convertible_to<int>; };
class X {
public:
int getInt(){
return 9;
}
};
class Y {};
template <typename T>
void f(T& v) {
// only for Y
std::cout << "Y" << std::endl;
}
template <HasGetInt T>
void f(T& v){
// only for X
int i = v.getInt();
std::cout << "X" << std::endl;
}
int main() {
X x;
f(x);
Y y;
f(y);
}
Check it out live.
You might use if constexpr from C++17:
template<typename T>
void f(T& v){
if constexpr(std::is_same_v<T, X>) { // Or better create trait has_getInt
int i = v.getInt();// I want this to be called for X only
}
// ...
}
Before, you will have to use overloads and SFINAE or tag dispatching.
Keep it simple and overload. Has worked since at least C++98...
template<typename T>
void f(T& v)
{
// do whatever
}
void f(X& v)
{
int result = v.getInt();
}
This is enough if there only ever one type with getInt function. If there's more, it's not so simple anymore. There are several ways to do it, here's one:
struct PriorityA { };
struct PriorityB : PriorityA { };
template<typename T>
void f_impl(T& t, PriorityA)
{
// generic version
}
// use expression SFINAE (-> decltype part)
// to enable/disable this overload
template<typename T>
auto f_impl(T& t, PriorityB) -> decltype(t.getInt(), void())
{
t.getInt();
}
template<typename T>
void f(T& t)
{
f_impl(t, PriorityB{ } ); // this will select PriorityB overload if it exists in overload set
// otherwise PriorityB gets sliced to PriorityA and calls generic version
}
Live example with diagnostic output.

In a template, if a dependent name is a function, call it

In my TClass<T>::foo() function, I'd like to invoke a T instance if and only if T is a function type.
#include <iostream>
#include <functional>
template<class T>
struct TClass
{
TClass(T value) : value(value) {}
T value;
void foo()
{
// if(value is std::function)
// call function;
}
};
int main()
{
TClass<int> t1{0};
t1.foo();
TClass<std::function<void()>> t2{[](){ std::cout << "Hello, World!\n"; }};
t2.foo();
}
How can I do that?
In C++11, the easiest way to do this is to re-deduce the value through a helper function:
template <typename U>
auto foo_helper(U const& f, int) -> decltype(f()) {
return f();
}
template <typename U>
void foo_helper(U const&, long) {}
void foo() {
foo_helper(value, 0);
}
The conversion from 0 to int is better than its conversion to long, so if the first overload is viable - it will be preferred. If the first overload isn't viable, then we call the second one.
If you really care only about std::function, then we can just have simpler overloads:
void foo_helper(std::function<void()> const& f) {
f();
}
template <typename T>
void foo_helper(T const&) { }
void foo() {
foo_helper(value);
}
In C++17 you can do:
void foo() {
if constexpr (std::is_invocable_v<T>) {
value();
}
}
If you only wants to allow std::function, you'll need your own trait, e.g.:
template <class T>
struct is_stdfunction: std::false_type {};
template <class T>
struct is_stdfunction<std::function<T>: std::true_type {};
template <class T>
constexpr bool is_stdfunction_v = is_stdfunction<T>::value;
// Then in foo():
void foo() {
if constexpr (is_stdfunction_v<std::decay_t<T>>) {
value();
}
}
Why not partial specialization ?
Consider:
#include <iostream>
#include <functional>
template<class T>
struct TClass {
TClass(T value) : value(value) {}
T value;
void foo() {
std::cout << "T - other" << std::endl;
}
};
template<class T>
struct TClass<std::function<T>> {
TClass(std::function<T> value) : value(value) {}
std::function<T> value;
void foo() {
std::cout << "std::function" << std::endl;
}
};

Forwarding params in C++

I have some class and wrapper around it. For example:
#include <iostream>
#include <string>
template<typename T>
class inner
{
public:
void f(T& v) { std::cout<<"lvalue: "<<v<<std::endl;}
void f(T&& v) { std::cout<<"rvalue: "<<v<<std::endl;}
};
template<typename T>
class wrapper
{
public:
template<typename _T>
void f(_T&& v) { i.f(std::forward<T>(v)); } //(1)
private:
inner<T> i;
};
int main()
{
wrapper<std::string> c;
//inner<std::string> c;
c.f("r");
std::string s = "l";
c.f(s);
}
In the case when c is inner output is correct:
rvalue: r
lvalue: l
But when c is wrapper output is not correct:
rvalue: r
rvalue: l
Why l-value became r-value?
And what the difference if wrapper's f definition on line (1) would be:
template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&
Because you're doing:
template<typename _T>
void f(_T&& v) { i.f(std::forward<T>(v)); } //(1)
^
T, not _T
You're always just using T, not the deduced type of v. For added clarity, you're actually doing:
template <typename _T>
void f(_T&& v) {
i.f(std::forward<std::string>(v));
}
And the type of std::forward<std::string>(v) is string&&.
For your second question:
template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&
Since _T will never deduce as a reference type here, std::forward<T>(v) will be equivalent to std::move(v) - it's just a cast to rvalue reference.

Ambiguity issue when deducing function call

I have the following bit of code which has two versions of the function foo. I'd like if a variable is passed for the foo that takes an AVar type to be called otherwise if a const is passed for the AConst version to be called.
#include <iostream>
template <typename T>
struct AConst
{
AConst(T x):t(x){}
const T t;
};
template <typename T>
struct AVar
{
AVar(const T& x):t(x){}
const T& t;
};
template <typename T>
void foo(AConst<T> a) { std::cout << "foo AConst\n"; }
template <typename T>
void foo(AVar<T> a) { std::cout << "foo AVar\n"; }
int main()
{
int i = 2;
foo(1);
foo(i);
return 0;
}
Currently the compiler gives me an ambiguity error. Not sure how to resolve it.
UPDATE: Based on Leonid's answer with a slight modification, here is the following solution which works as required:
template <typename T>
void foo_x(AConst<T> a) { std::cout << "foo AConst\n"; }
template <typename T>
void foo_x(AVar<T> a) { std::cout << "foo AVar\n"; }
template <typename T>
void foo(const T& a) { foo_x(AConst<T>(a));}
template <typename T>
void foo(T& a) { foo_x(AVar<T>(a));}
Compiler can not deduce your T.
To help him, simplify parameter type:
template <typename T>
void foo(const T& a) { AConst<T> aa(a); std::cout << "foo AConst\n"; }
template <typename T>
void foo(T& a) { AVar<T> aa(a); std::cout << "foo AVar\n"; }
Use casting to eliminate ambiguity errors. In this case you could cast "1" as an AConst if I remember right. I don't remember the exact syntax for casting to a template type...maybe something like:
foo( (AConst<int>) 1); .. or something to that effect.
The compiler can't select appropriate function. You may want to declare 2 functions with different names:
template <typename T>
void fooConst(AConst<T> a) { std::cout << "foo AConst\n"; }
template <typename T>
void fooVar(AVar<T> a) { std::cout << "foo AVar\n"; }
Or, you may choose to use functions you have this way:
int main()
{
int i = 2;
foo(AConst<int>(1));
foo(AVar<int>(i));
return 0;
}
In general, you doesn't provide enough information to the compiler. You're the only who knows what instance should be used in the main function. Probably, if you would describe in more details what is the purpose of this code, the solution would be more specific.
You could pass in the full class template to the function like so
#include <iostream>
template <typename T>
struct AConst
{
AConst(T x) :t(x){ std::cout << "AConst\n"; }
const T t;
};
template <typename T>
struct AVar
{
AVar(const T& x) :t(x){ std::cout << "AVar\n"; }
const T& t;
};
template <typename T1>
void foo(T1 a){}
int main()
{
int i = 2;
foo<AConst<int>>(1);
foo<AVar<int>>(i);
return 0;
}