#include <bits/stdc++.h>
using namespace std;
template<class T = string>
void f(T &&s) {
cout << s << endl;
}
int main() {
string s("1234");
f(s);
f("1234");
return 0;
}
Can be compiled.
#include <bits/stdc++.h>
using namespace std;
void f(string &&s) {
cout << s << endl;
}
int main() {
string s("1234");
f(s);
f("1234");
return 0;
}
I replace T to string, the code can not be compiled.
error:
❯ g++-8 -std=c++11 a.cpp && ./a.out
a.cpp: In function 'int main()':
a.cpp:10:11: error: cannot bind rvalue reference of type 'std::__cxx11::string&&' {aka 'std::__cxx11::basic_string<char>&&'} to lvalue of type 'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'}
f(s);
^
a.cpp:4:10: note: initializing argument 1 of 'void f(std::__cxx11::string&&)'
void f(string &&s) {
^
I'm so confused.
There are some exceptions to template type inference.
If a function template receives an rvalue reference and we passed in an lvalue reference,compiler will inference it as a lvalue reference.That is the reason that std::move works correctly.
template <typename T>
typename remove_reference<T>::type&& move(T&& t)
{
return static_cast<typename remove_reference<T>::type&&>(t);
}
Related
Why this code snippet works with C++17 whereas the compiler complains when using C++11(i.e https://godbolt.org/z/71G91P)?
Are there any potential problems with this code snippet?
#include<iostream>
class ctx
{
public:
int map_create(void*){std::cout << "haha" << std::endl; return 0;};
};
ctx obj;
typedef int (ctx::*ctx_mem_func)(void*);
template <ctx_mem_func func>
int regHelper(void*)
{
((&obj)->*func)(nullptr);
return 0;
}
constexpr ctx_mem_func testFunc = &ctx::map_create;
typedef int(*callBackFunc)(void*);
int reg(callBackFunc)
{
return 0;
}
int main()
{
reg(regHelper<testFunc>);
//But this expression is ok.
reg(regHelper<&ctx::map_create>);
std::cout << "this is a test" << std::endl;
}
Here are the error messages when using c++11(gun 10.0.2):
<source>: In function 'int main()':
<source>:30:28: error: no matches converting function 'regHelper' to type 'callBackFunc {aka int (*)(void*)}'
reg(regHelper<testFunc>);
^
<source>:13:5: note: candidate is: template<int (ctx::* func)(void*)> int regHelper(void*)
int regHelper(void*)
^
This is a difference between C++14 and C++17. Simplified:
int f();
template<int (&)()> struct S {};
constexpr auto& q = f;
using R = S<q>; // valid in C++17, invalid in C++14
The change is to Allow constant evaluation for all non-type template arguments, meaning that now a constexpr variable naming a function (member function, etc.) is permissible as an NTTP where previously only the actual name of the function was permitted.
I'm trying to map string to function pointer, so that I can call the function with iter->second(arg) instead of if-else.
I have written a simple one without class, and it works as expected.
But when I modify it as below, it shows compile errors.
#include <functional>
#include <iostream>
#include <unordered_map>
#include <string>
using std::string;
class A{
private:
int a(int num, string s) { return s.size() + num; }
int b(int num, string s) { return num - s.size(); }
public:
void ido(string str){
typedef std::function<int(int, string)> process_func;
std::unordered_map<string, process_func> m;
m.insert(std::make_pair<string, process_func>("a", &A::a));
// using std::placeholders::_1;
// m.insert(std::make_pair<string, process_func>("a", std::bind(&A::a, this, _1)));
// m["a"] = std::bind(&A::a, this, _1);
// m.insert({{"a", &A::a}, {"b", &A::b}});
auto x = m.find(str);
if(x == m.end()) {
std::cout << "Not supported!" << std::endl;
}
std::cout << x->second(10, "hello") << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
a.ido(string(argv[1]));
return 0;
}
The errors are:
function.cc: In member function ‘void A::ido(std::string)’:
function.cc:17:65: error: no matching function for call to ‘make_pair(const char [2], int (A::*)(int, std::string))’
m.insert(std::make_pair<string, process_func>("a", &A::a));
^
function.cc:17:65: note: candidate is:
In file included from /usr/include/c++/4.8.2/utility:70:0,
from /usr/include/c++/4.8.2/tuple:38,
from /usr/include/c++/4.8.2/functional:55,
from function.cc:1:
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_Tp>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
make_pair(_T1&& __x, _T2&& __y)
^
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template argument deduction/substitution failed:
function.cc:17:65: note: cannot convert ‘&A::a’ (type ‘int (A::*)(int, std::string) {aka int (A::*)(int, std::basic_string<char>)}’) to type ‘std::function<int(int, std::basic_string<char>)>&&’
m.insert(std::make_pair<string, process_func>("a", &A::a));
What does the error mean? How to fix it?
While your functions 'a' and 'b' do not depend on 'this' (they do not access anything inside class A), the compiler is not smart enough to deduce this. So the error means that you are trying to convert 'pointer to method' to 'pointer to function', which is incorrect conversion. 'Pointer to method' requires and object to be called on. You need to declare methods 'a' and 'b' as 'static' to indicate that they are actually standalone functions, not methods of the class.
The following test program reproduces compilation errors within the context of a larger program:
#include <algorithm>
#include <iostream>
#include <vector>
using std::for_each;
using std::vector;
using std::cout;
using std::endl;
template<typename T, typename C = vector<T>>
class display_container{
public:
display_container(const C& cr):this->cr(cr){this->();}
~display_container(){}
private:
constexpr void operator () (void){if(cr.empty()){cout << "NULL" << " ";} else{for_each(cr.begin(), cr.end(), [](const T& crt){cout << crt << " ";});}}
const C& cr;
};
int main (void){
int n = 5;
vector<int> vec(n, 0);
display_container d(vec);
cout << endl;
return 0;
}
The following is a log of the compiler errors:
g++ -ggdb -std=c++17 -Wall -Werror=pedantic -Wextra -c code.cpp
code.cpp: In constructor ‘display_container<T, C>::display_container(const C&)’:
code.cpp:12:40: error: expected identifier before ‘this’
display_container(const C& cr):this->cr(cr){this->();}
^~~~
code.cpp:12:40: error: expected ‘{’ before ‘this’
code.cpp: In function ‘int main()’:
code.cpp:23:28: error: class template argument deduction failed:
display_container d(vec);
^
code.cpp:23:28: error: no matching function for call to ‘display_container(std::vector<int>&)’
code.cpp:12:9: note: candidate: template<class T, class C> display_container(const C&)-> display_container<T, C>
display_container(const C& cr):this->cr(cr){this->();}
^~~~~~~~~~~~~~~~~
code.cpp:12:9: note: template argument deduction/substitution failed:
code.cpp:23:28: note: couldn't deduce template parameter ‘T’
display_container d(vec);
^
code.cpp:10:7: note: candidate: template<class T, class C> display_container(display_container<T, C>)-> display_container<T, C>
class display_container{
^~~~~~~~~~~~~~~~~
code.cpp:10:7: note: template argument deduction/substitution failed:
code.cpp:23:28: note: ‘std::vector<int>’ is not derived from ‘display_container<T, C>’
display_container d(vec);
^
make: *** [makefile:20: code.o] Error 1
I presume that the remaining errors trickle down from the first error related to the inline constructor definition for the display_container template class.
Any suggestions on what is wrong with the code related to inline constructor definition?
TIA
The compiler can not fetch the template type of vector yet:
#include <algorithm>
#include <iostream>
#include <vector>
using std::for_each;
using std::vector;
using std::cout;
using std::endl;
template<typename T, typename C = vector<T>>
class display_container{
public:
display_container(const C& cr): cr(cr) { (*this)(); }
~display_container(){}
private:
constexpr void operator () (void){if(cr.empty()){cout << "NULL" << " ";} else{for_each(cr.begin(), cr.end(), [](const T& crt){cout << crt << " ";});}}
const C& cr;
};
int main (void){
int n = 5;
vector<int> vec(n, 0);
display_container<int> d(vec);
cout << endl;
return 0;
}
You couldn't (and don't need) qualify data members in member initializer list by this, they're expected to be the identifier. The correct syntax should be
display_container(const C& cr):cr(cr){(*this)();}
You should dereference on this and then call operator() on it (as showed abolve), or you can call operator() explicitly like this->operator()(); (which looks ugly).
You should specify the template argument for display_container.
display_container<int> d(vec);
LIVE
I am using compiler g++ 6.3.0 (c++14).
In the code-
#include<iostream>
int f(auto a){return a;}
int f1(auto (*g)(int),int a) {return g(a);}
main()
{
std::cout<< f1(f,8);
}
Compiler is not able to deduce the return type of g.
It shows following error-
temp.cpp: In function 'int main()':
temp.cpp:9:20: error: no matching function for call to 'f1(<unresolved overloaded function type>, int)'
std::cout<< f1(f,8);
^
temp.cpp:5:5: note: candidate: template<class auto:2> int f1(auto:2 (*)(int), int)
int f1(auto (*g)(int),int a) {return g(a);}
^~
temp.cpp:5:5: note: template argument deduction/substitution failed:
temp.cpp:9:20: note: couldn't deduce template parameter 'auto:2'
std::cout<< f1(f,8);
^
But no error comes in the code-
#include<iostream>
int f(int /* <<<<< */ a){return a;} // only (auto a) is changed to (int a)
int f1(auto (*g)(int),int a) {return g(a);}
main()
{
std::cout<< f1(f,8);
}
Help me understand the error...
int f(auto a){return a;}
is equivalent to
template <typename T>
int f(T a){return a;}
You cannot take the address of a template (or overload set) - that is why you're seeing that error. Workarounds:
Take the address of the instantiation you want:
return f1(f<int>,8);
Make f1 accept auto and pass a lambda:
int f1(auto g, int a) {return g(a);}
int main()
{
std::cout<< f1([](auto x){ f(x); },8);
}
The following code does not compile with G++ (although I believe it should):
#include <iostream>
template <unsigned N>
struct foo_traits {
typedef const char ArrayArg[N];
typedef int Function (ArrayArg *);
};
template <unsigned N>
int foo (typename foo_traits<N>::Function *ptr) {
return ptr(&"good");
}
int bar (const char (*x)[5]) {
std::cout << *x << "\n";
return 0;
}
int main ()
{
return foo(bar);
}
I checked this with GCC 4.4 through 4.7, and I get a template argument deduction failure. With 4.7.1:
prog.cpp: In function ‘int main()’:
prog.cpp:21:19: error: no matching function for call to ‘foo(int (&)(const char (*)[5]))’
prog.cpp:21:19: note: candidate is:
prog.cpp:10:5: note: template<unsigned int N> int foo(typename foo_traits<N>::Function*)
prog.cpp:10:5: note: template argument deduction/substitution failed:
prog.cpp:21:19: note: couldn't deduce template parameter ‘N’
If I use an explicit template argument (i.e., foo<5>(bar)), it compiles fine. If I use a version of the code without the typedefs, it compiles fine:
#include <iostream>
template <unsigned N>
int fixfoo (int (*ptr) (const char (*)[N])) {
return ptr(&"good");
}
int bar (const char (*x)[5]) {
std::cout << *x << "\n";
return 0;
}
int main ()
{
return fixfoo(bar);
}
Is the failing code supposed to compile (i.e., did I make a silly mistake)?
int foo(typename foo_traits<N>::Function *ptr);
The signature makes it a non-deductible context, so you must include the template arguments so that the value N is known and so consequentially the type of the pointer ptr be known as well.
Your second example compiles because the type of the signature through bar can be deduced.