The following code give me an error that 'print2' is not a member of 'N' when using both clang and gcc:
#include <stdio.h>
struct Printer
{
template<class T>
void print(T t)
{
N::print2(*this, t);
}
};
namespace N
{
void print2(Printer& p, int v)
{
printf("%d\n", v);
}
}
int main()
{
Printer p;
p.print(1);
}
If I remove the namespace N and make the print2 function global it works. Why is the lookup different when the function is put in a namespace and when it's not? Unfortunately I can't move the print2 function before struct Printer, which would've been the obvious solution.
Here I am simply declaring the function before Printer, while defining the logic of the function afterwards.
#include <stdio.h>
namespace N {
void print2(int);
}
struct Printer
{
template<class T>
void print(T t)
{
N::print2(t);
}
};
namespace N
{
void print2(int v)
{
printf("%d\n", v);
}
}
int main()
{
Printer p;
p.print(1);
}
Related
Consider following code snippet:
class Foo {
public:
void bar(std::size_t){}
void bar(const char* ){}
};
int main() {
auto foo = Foo{};
foo.bar(0);
}
It produces ambiguous calls errors (check here). But I think from programmer's perspective it is pretty obvious that I want to call overload with std::size_t. My question is if anything can be done so this code does not produce errors and calls size_t overload?
can be done like this in C++ 20
#include <cstdint>
#include <iostream>
#include <type_traits>
class Foo {
public:
template <typename T>
requires std::is_integral_v<T>
void bar(T){
std::cout<<"hello size_T";
}
void bar(const char* ){
std::cout<<"hello";
}
};
int main() {
auto foo = Foo{};
foo.bar(25);
}
In modern c++ (at least c++17), we prefer to pass string_view as argument over const char* for the none owner transfer cases, so a considerable choice:
#include <cctype>
#include <string>
class Foo {
public:
void bar(std::size_t){}
void bar(std::string_view){}
};
int main() {
auto foo = Foo{};
foo.bar(0);
}
Online demo
In below C++ 20, this works well.
#include <iostream>
class Foo {
public:
template <typename T>
void bar(T) {
std::cout << "hello T" << std::endl;
}
void bar(const char* c) {
std::cout << c << std::endl;
}
};
int main() {
auto foo = Foo{};
foo.bar(0);
foo.bar("test.");
}
This works in C++23:
foo.bar(0zu);
and this works pre-C++23:
foo.bar(size_t{0});
the title and the code is self-explanatory,
Is such a thing possible?how?
Is it encouraged? if not, what is the alternative?
thanks
#include <iostream>
using namespace std;
namespace A
{
void foo()
{
cout << "In A\n";
}
}
namespace B
{
void foo()
{
cout << "In B\n";
}
}
template <typename X>
struct Foo {
void foo()
{
X::foo();
}
};
int main()
{
Foo<A> _foo;
_foo.foo();
return 0;
}
You cannot use a namespace as a template type (namespaces are not types); your code does not compile. The best you can hope for is to use Argument Dependent Lookup (ADL), but it won't work for functions taking no parameters.
If you rename your member function, you can find it via ADL by using a proxy tag:
namespace A
{
struct tag {};
void foo(tag)
{
std::cout << "In A\n";
}
}
namespace B
{
struct tag {};
void foo(tag)
{
std::cout << "In B\n";
}
}
template<class Tag>
struct Foo {
void fooADL()
{
foo(Tag{});
}
};
int main()
{
Foo<A::tag> f;
f.fooADL();
}
Is such a thing possible?
No, you can't parametrise a namespace.
if not, what is the alternative?
Use classes, rather than namespaces, to provide parametrisable scopes for the functions:
struct A {
static void foo();
};
struct B {
static void foo();
}
I just realized that trying to get the return type of a function via decltype does not involve ADL (argument-dependent-lookup) on VS2012 (tested using cl.exe V17.00.60610.1).
The following example
#include <stdio.h>
#include <typeinfo>
namespace A {
int Func(void const *) {
printf("A::Func(void const *)\n");
return 0;
}
template <typename T> void Do(T const &t) {
Func(&t);
}
template <typename T> void PrintType(T const &t) {
printf("Type: %s\n", typeid(decltype(Func(&t))).name());
}
}
namespace B {
struct XX { };
float Func(XX const *) {
printf("B::Func(XX const *)\n");
return 0.0f;
}
}
int main(int argc, char **argv) {
B::XX xx;
A::Do(xx);
A::PrintType(xx);
return 0;
}
Gives
B::Func(XX const *)
Type: int
on VS2012
but (what is expected):
B::Func(XX const *)
Type: f
on gcc 4.7.3.
So ADL works when calling the function (line 1 in output) but not when used inside decltype on VS2012.
Or am I missing some different point?
A minimal test case is:
namespace N
{
struct C {};
C f(C) {};
}
N::C c1;
decltype(f(c1)) c2;
If the compiler doesn't support ADL inside decltype, then the above will not compile.
I'm told it does compile, so maybe it is the interaction between ADL and template instantiation that is the problem.
If find it amusing that the IDE/Intellisense whatsoever seems to do the lookup correctly but the compiler does not.
This example shows no intellisense errors and a is displayed to be of type size_t when hovering it.
#include <iostream>
namespace A
{
struct C {};
size_t f(C*) { return 5U; };
}
namespace B
{
void f(void *) { };
void f2 (A::C x)
{ decltype(f(&x)) a; std::cout << typeid(a).name() << std::endl; }
}
int main (void)
{
A::C c;
B::f2(c);
}
The compiler stops with Error C2182 and complains about a variable of type void.
It seems to be a problem independant of templates.
I am trying to create a generic function map using templates.The idea is to inherit from this generic templated class with a specific function pointer type. I can register a function in the global workspace, but I'd rather collect all the functions together in the derived class and register these in the constructor. I think I am almost here but I get a compile error. Here is a stripped down version of my code:
#include <iostream>
#include <string>
#include <map>
#include <cassert>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef int (*F)(int);
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", f2); // This does not
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}
The error I get is:
templatefunctions.cpp: In constructor ‘IntFunctionMap::IntFunctionMap()’:
templatefunctions.cpp:33: error: no matching function for call to ‘IntFunctionMap::registerFunction(const char [3], <unresolved overloaded function type>)’
templatefunctions.cpp:15: note: candidates are: void FunctionMap<T>::registerFunction(std::string, T) [with T = int (*)(int)]
Juan's answer is correct: member functions have an implicit first parameter, which is a pointer to the type of which they are a member. The reason your code fails to compile is that your map supports function pointers with type int (*)(int), but the type of f2 is int (IntFunctionMap::*)(int).
In the specific case that you show here, you can use std::function, which implements types erasure, to present free functions and member functions as the same type. Then you could do what you are trying to do. Note: this requires C++11.
#include <iostream>
#include <string>
#include <map>
#include <cassert>
#include <function>
#include <bind>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef std::function<int (int)> F;
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", std::bind(&f2, this, _1)); // This should work, too!
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}
Have a problem about how to call the generic template version in a specialization version.
Here is the sample code. But the "vector::push_back(a)" calls itself recursively.
#include <iostream>
#include <vector>
using namespace std;
namespace std
{
template<>
void vector<int>::push_back(const int &a)
{
cout << "in push_back: " << a << endl;
vector::push_back(a); // Want to call generic version
}
}
int main()
{
vector<int> v;
v.push_back(10);
v.push_back(1);
return 0;
}
When you create specialization for some template (no difference class of function), you tell to compiler to generate that one instead of general. So in fact if you have specialization you have no general version for that specialization and you can't call it, because it doesn't exists.
You can simply extract the code into another template function:
template<typename T>
void baseF(T t) { ... }
template<typename T>
void F(T t) { baseF<T>(t); }
template<>
void F<int>(int t) { baseF<int>(t); }
Well, to complement, I think it works for template function specification in some situations.
#include <iostream>
#include <vector>
using namespace std;
class Base
{
public:
virtual int test() {return 0;}
};
class Derived : public Base
{
public:
virtual int test() {return 1;}
};
template<class T>
void TestOutput(T* a)
{
cout << a->test() << endl;
}
template<>
void TestOutput(Derived* a)
{
cout << "something else" << endl;
TestOutput<Base>(a);
}
int main()
{
Derived d;
TestOutput(&d);
}
I compiled it with visual studio 2013 and the output is:
something else
1
Although I don't think you can always find a TestOutput function of Base to call the generic one.