I learn the C++ template name binding and instantiation recently, and find the strange behavious in the following code.
#include <iostream>
using namespace std;
template <typename T>
int f(T a)
{
return g(a); // g() should be dependent name
}
struct C {};
int g(C c)
{
return 0;
}
int g(int i)
{
return i;
}
int main()
{
// Works!
int z = f(C{});
// Error: no declarations were found by argument-dependent lookup at the point of instantiation
//int z = f(10);
cout << z << endl;
return 0;
}
I think g(T) should be dependent name and int z = f(10) should work like int z = f(C{}). But gcc-6.3.0 complains:
g++ -g -o tmpl tmpl.cpp
tmpl.cpp: In instantiation of ‘int f(T) [with T = int]’:
tmpl.cpp:29:17: required from here
tmpl.cpp:8:13: error: ‘g’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
return g(a);
~^~~
tmpl.cpp:18:5: note: ‘int g(int)’ declared here, later in the translation unit
int g(int i)
Related
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);
}
I have two function templates A and B. I define A and then B in the same file. Now I would like to call B in A. How can I realize this? Normal function prototype doesn't work in this case. (Please assume you cannot change the order of A and B or split files.)
#include <iostream>
template <class Type>
Type A(Type x) {
return 2 * B(x);
}
template <class Type>
Type B(Type x) {
return 3 * x;
}
int main() {
int x = 3;
std::cout << A(x) << "\n"; //=> ERROR
}
ERROR from g++:
test.cpp: In instantiation of ‘Type A(Type) [with Type = int]’:
test.cpp:40:21: required from here
test.cpp:29:17: error: ‘B’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
return 2 * B(x);
~^~~
test.cpp:33:6: note: ‘template<class Type> Type B(Type)’ declared here, later in the translation unit
Type B(Type x) {
^
If by prototype you mean declaration, it certainly does work in this case!
You can declare a function template just fine:
#include <iostream>
// Non-defining declaration B
template <class Type>
Type B(Type x);
// Defining declaration A
template <class Type>
Type A(Type x) {
return 2 * B(x);
}
// Defining declaration B
template <class Type>
Type B(Type x) {
return 3 * x;
}
int main() {
int x = 3;
std::cout << A(x) << "\n"; //=> NO ERROR
}
(live demo)
Trying to propose a solution to another question, I bumped (again) my nose against code that compile and work with clang++ (3.5) but give compilation error with g++ (4.9.2)
The following is a simplified minimal (I hope) example
#include <iostream>
class foo;
template <std::size_t>
struct bar;
template <>
struct bar<0U>
{ static void baz (foo const & f); };
class foo
{
int i = 42;
template <std::size_t I>
friend void bar<I>::baz (foo const &);
};
void bar<0U>::baz (foo const & f)
{ std::cout << f.i << std::endl; }
int main()
{
foo f;
bar<0U>::baz(f);
}
The error from my g++ is
test_114-98,11,14,clang.cpp:18:41: error: member ‘void bar<<anonymous> >::baz(const foo&)’ declared as friend before type ‘bar<<anonymous> >’ defined
friend void bar<I>::baz (foo const &);
^
test_114-98,11,14,clang.cpp: In static member function ‘static void bar<0ul>::baz(const foo&)’:
test_114-98,11,14,clang.cpp:15:13: error: ‘int foo::i’ is private
int i = 42;
^
test_114-98,11,14,clang.cpp:22:19: error: within this context
{ std::cout << f.i << std::endl; }
^
My question, as usual, is: who's right and who's wrong.
Compiling the following code
template <typename X, typename F>
auto apply(X x, F f)
{
return f(x);
}
template <typename Y>
auto add_value(Y y)
{
return [y](auto x)
{
return x + y;
};
}
int main()
{
apply(1, add_value(2));
}
with g++ (e.g. v. 5.4) gives shadow warnings.
$ g++ -Wshadow -Werror -std=c++14 shadow_test.cpp
shadow_test.cpp: In instantiation of ‘add_value(Y)::<lambda(auto:1)> [with auto:1 = int; Y = int]’:
shadow_test.cpp:4:13: required from ‘auto apply(X, F) [with X = int; F = add_value(Y) [with Y = int]::<lambda(auto:1)>]’
shadow_test.cpp:18:26: required from here
shadow_test.cpp:10:22: error: declaration of ‘int x’ shadows a parameter [-Werror=shadow]
return [y](auto x)
^
shadow_test.cpp:2:14: note: shadowed declaration is here
auto apply(X x, F f)
^
cc1plus: all warnings being treated as errors
I do not understand why. Can anybody explain?
Must be a bug.
The variable is not being shadowed as it is not in the enclosing scope of the lambda, however it does produce the correct result.
VS2015 produces no warnings.
Clang produces no warnings.
This is speculative, but what is probably happening is the following substitution (or something like it):
#include <iostream>
template <typename X, typename Y>
auto add_value(X x, Y y)
{
auto f = [y](auto x)
{
return x + y;
};
return f(x);
}
int main()
{
std::cout << add_value(1, 2);
}
This program does produce a shadow warning on Clang, but even then it produces the correct result. VS2015 still does not consider this worthy of a warning, but it is probably wrong because names from the enclosing scope of the lambda are also in the scope of the lambda. If they are not captured they may be used, but may not be odr-used as explained here.
Hi the following program works with g++ 4.9.2 (Ubuntu 4.9.2-10ubuntu13) but the virtual keyword is required for the function get :
//g++ -std=c++14 test.cpp
//test.cpp
#include <iostream>
using namespace std;
template<typename T>
constexpr auto create() {
class test {
public:
int i;
virtual int get(){
return 123;
}
} r;
return r;
}
auto v = create<int>();
int main(void){
cout<<v.get()<<endl;
}
If I omit the virtual keyword, I get the following error :
test.cpp: In instantiation of ‘constexpr auto create() [with T = int]’:
test.cpp:18:22: required from here
test.cpp:16:1: error: body of constexpr function ‘constexpr auto create() [with T = int]’ not a return-statement
}
^
How can I get the code above to work (with g++) without having to use the virtual keyword?
Classes defined inside a function cannot be accessed outside the function.
My suggestion are: declare test outside the function and add const qualifier to get function.
#include <iostream>
using namespace std;
class test {
public:
int i;
int get() const {
return 123;
}
};
template<typename T>
constexpr test create() {
return test();
}
auto v = create<int>();
int main(void){
cout<<v.get()<<endl;
}