I have two template classes and normally I would prefer the foo version of the Search class. But sadly my compiler can not understand the foo version because of the missing c++11 support. (He will not understand this line: template <typename U = _Format>)
The bar version will create an instance of the _Format type to call the right delegate. So also a constructor is called! Would this be a performance issue compared to the Foo version? (I know this would be this is like premature optimization, but I'm interested)
#include <iostream>
struct format1 {
format1(void) { }
};
struct format2 {
format2(void) { }
};
namespace foo
{
template <typename _Format>
class Search
{
public:
void createData()
{
doCreateData();
}
private:
template <typename U = _Format>
void doCreateData();
template <>
void doCreateData<format1>()
{
using namespace std;
cout << "Format1" << endl;
}
template <>
void doCreateData<format2>()
{
using namespace std;
cout << "Format2" << endl;
}
};
}
namespace bar
{
template <typename _Format>
class Search
{
public:
void createData(void)
{
doCreateData(_Format());
}
private:
void doCreateData(format1)
{
using namespace std;
cout << "Format1" << endl;
}
void doCreateData(format2)
{
using namespace std;
cout << "Format2" << endl;
}
};
}
int main(int argc, char *argv[])
{
(void)argc; (void)argv;
bar::Search<format2> search;
search.createData();
}
Related
This question already has answers here:
Alternative to using namespace as template parameter
(2 answers)
Closed 4 months ago.
Is there a way to use a namespace as a template?
I need to call the same function but from a different namespaces.
Something like that:
There are two namespaces here myNamespace1, myNamespace2 that contain a function with the same name - func()
#include <iostream>
using namespace std;
namespace myNamespace1 {
void func()
{
std::cout<<"myNamespace1" << std::endl;
}
}
namespace myNamespace2 {
void func()
{
std::cout<<"myNamespace2" << std::endl;
}
}
template<auto T>
class A {
public:
void func()
{
T::func();
}
};
}
int main() {
using namespace myNamespace1;
using namespace myNamespace2;
A<myNamespace1> a1;
a1.func(); // output: myNamespace1
A<myNamespace2> a2;
a2.func(); // output: myNamespace2
return 0;
}
A namespace may not be used as a template parameter. But you can use for example a non-type template parameter that denotes a function like for example
#include <iostream>
namespace myNamespace1 {
void func()
{
std::cout << "myNamespace1" << std::endl;
}
}
namespace myNamespace2 {
void func()
{
std::cout << "myNamespace2" << std::endl;
}
}
template<void ( &Func )()>
class A {
public:
void func()
{
Func();
}
};
int main()
{
A<myNamespace1::func> a1;
a1.func();
A<myNamespace2::func> a2;
a2.func();
}
The program output is
myNamespace1
myNamespace2
You can create tag classes:
class myNamespace1Tag {};
class myNamespace2Tag {};
template<typename T>
using A_in = std::conditional_t<std::is_same_v<T, myNamespace1Tag>, myNamespace1::A, std::conditional_t<std::is_same_v<T, myNamespace2Tag>, myNamespace2::A, void>;
A_in<myNamespace1Tag> a1;
I would like to know how to make a template with an own class:
#include <iostream>
using namespace std;
template<C cc> void A()
{
cout << cc.l << endl;
}
int main()
{
C cc;
A<cc>();
}
class C
{
public:
int l = 10;
};
But it doesn't work, so how to use that class, like a non-generic class parameter, like here:
#include <iostream>
using namespace std;
template<int i> void A()
{
cout << i << endl;
}
int main()
{
A<100>();
}
You can do it as shown below with C++20(&onwards):
//moved definition of C before defining function template `A`
struct C
{
int l = 10;
};
template<C cc> void A()
{
cout << cc.l << endl;
}
int main()
{
//--vvvvvvvvv--------->constexpr added here
constexpr C cc;
A<cc>();
}
Working demo
Two changes have been made:
As template arguments must be compile time constant, constexpr is used.
The definition of C is moved before the definition of function template.
I would like to create a C++ class with a default template parameter. However, I am having the following error:
error: invalid use of incomplete type
The code is the follow:
#include <iostream>
#include <string>
#include <array>
typedef std::array<double, 3> vec;
enum Op {Op1, Op2, Op3};
template<class T, enum Op S=Op1>
class classA
{
public:
class classInsideA
{
public:
classInsideA() {}
void tst()
{
std::cout << "inside A"<< std::endl;
}
};
void foo();
};
template<class T>
void classA<T>::foo() // not working
{
std::cout<< "I am being called in here" << std::endl;
}
int main(int argc, char** argv)
{
classA<vec> obj2;
return 0;
}
I would like that the default template would not change any of the current syntax in the class classA.
How can I fix this?
Edit:
Making the function have 2 template parameters, works.
template<class T, Op S>
void classA<T, S>::foo()
{
std::cout<< "I am being called in here" << std::endl;
}
But if the function has a default parameter, why do I need to specify the two templates. Shouldn't assume the default one?
Simply a typo I believe! You class has two template parameters and your function definition must also use both. See the full example below or here
typedef std::array<double, 3> vec;
enum Op {Op1=99, Op2, Op3};
template<class T, Op S=Op1>
class classA
{
public:
class classInsideA
{
public:
classInsideA() {}
void tst()
{
std::cout << "inside A we use Op value"<< S << std::endl;
}
};
classInsideA dummy;
void foo();
};
template<class T, Op S>
void classA<T, S>::foo() // not working
{
std::cout<< "I am being called in here and we use Op value" << S << std::endl;
}
int main(int argc, char** argv)
{
classA<vec> obj2;
obj2.dummy.tst();
obj2.foo();
return 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();
}
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.