When I tried to write something like this:
#include <iostream>
template <class T>
class A
{
public:
static void doit();
};
template <>
static void A<int>::doit()
{
std::cout << "int" << std::endl;
}
template <>
static void A<double>::doit()
{
std::cout << "double" << std::endl;
}
int main()
{
A<int>::doit();
A<double>::doit();
}
I got a compile error:
Specializing the whole class is ok. I just want to know is there any way to specialize only the static function?
You should specify static keyword only once, in declaration.
Try this:
template<>
void A<int>::doit()
{
std::cout << "int" << std::endl;
}
template<>
void A<double>::doit()
{
std::cout << "double" << std::endl;
}
Related
I have a class, classB which has several functions which I would like to specialize based on an enumerator template S.
I have the following example:
#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 innerClassA
{
public:
void foo() const
{
std::cout <<"Operation 1" << std::endl;
}
};
};
template<class T>
class classB
{
public:
template <Op S = Op1>
void myFunc()
{
typename classA<T, S>::template innerClassA myInnerClassObj;
for (int i = 0; i < 10; i++)
myInnerClassObj.foo();
}
// Other functions the I would like to able to speciallize afterwards based on template S
void myFunc2() { std::cout << "Func 2" << std::endl; }
void myFunc3() { std::cout << "Func 3" << std::endl; }
};
template<>
void classA<vec, Op2>::innerClassA::foo() const
{
std::cout << "Operation 2" << std::endl;
}
template<>
void classA<vec, Op3>::innerClassA::foo() const
{
std::cout << "Operation 3" << std::endl;
}
int main(int argc, char** argv)
{
classB<vec> obj;
obj.myFunc();
obj.myFunc2();
obj.myFunc<Op2>();
obj.myFunc<Op3>();
return 0;
}
In the above example. The function myFunc has a template parameter based on the enumerator. In the main function, I can call the specialized version based on the value of the enumerator. I would also like to do the same for the other functions,myFunc2 however, always having to put:
template <Op S = Op1>
someFunction()
is quite bothersome. Is there any other way to specify that all functions in a class have a default template based on the enumerator?
Kind regards
No, there is not, apart from macros.
#define OPFUNC template<Op S = Op1> void
OPFUNC myFunc() {}
OPFUNC myFunc2() {}
...
#undef OPFUNC
Based on this SO answer, I was experimenting with something similar but with a pointer:
#include <iostream>
class Bar {
public:
virtual ~Bar() {}
};
class Foo: Bar {
public:
Foo() { std::cout << "Foo::Foo()" << std::endl; }
~Foo() override { std::cout << "Foo::~Foo()" << std::endl; }
};
class Faz {
public:
Faz() { std::cout << "Faz::Faz()" << std::endl; }
~Faz() { std::cout << "Faz::~Faz()" << std::endl; }
};
template <typename T>
typename std::enable_if<std::is_base_of<Bar, std::remove_pointer<T>>::value>::type
func(char const* type, T) {
std::cout << type << " is derived from Bar" << std::endl;
}
template <typename T>
typename std::enable_if<!std::is_base_of<Bar, std::remove_pointer<T>>::value>::type
func(char const* type, T) {
std::cout << type << " is NOT derived from Bar" << std::endl;
}
int main()
{
func("std::unique_ptr<Foo>", std::unique_ptr<Foo>());
func("std::unique_ptr<Faz>", std::unique_ptr<Faz>());
}
cout is :
std::unique_ptr<Foo> is NOT derived from Bar
std::unique_ptr<Faz> is NOT derived from Bar
Why does !std::is_base_of<Bar, type_identity<std::remove_pointer<T>>>::value always evaluate as true? I assumed (as a beginner):
std::unique_ptr<Foo> is derived from Bar
std::unique_ptr<Faz> is NOT derived from Bar
I'm probably missing something stupid.
std::remove_pointer<> acts on raw pointer types.
The smart pointer's type is not related to the class hierarchy of referent type
I'm experimenting with a class which is a wrapper of multiple modules. Each module needs some configuration. I try to solve this with a variadic template functions to ensure at compiletime, that each module which should be generated has it's configuration data given.
The only problem left is that the template argument deduction/substitution is failing for my creation function template. If the whole wrapper would be a templated class it would work.
Following I'm providing a little example of the problem. I tried to keep it as simple as possible.
class ClassA{};
class ClassB{};
template<class Module>
class FactoryModuleConfig;
template<>
class FactoryModuleConfig<ClassA>{
public:
FactoryModuleConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
virtual ~FactoryModuleConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
template<>
class FactoryModuleConfig<ClassB>{
public:
FactoryModuleConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
virtual ~FactoryModuleConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
template< class... Args >
class FactoryConfig;
template<class Arg, class... Args>
class FactoryConfig<Arg, Args...> : public FactoryModuleConfig<Arg>, public virtual FactoryConfig<Args...>
{
public:
FactoryConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
virtual ~FactoryConfig( ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
template<>
class FactoryConfig<>
{
public:
FactoryConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
virtual ~FactoryConfig( ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
class myFactoryConfig : public FactoryConfig<ClassA,ClassB>{
public:
myFactoryConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
virtual ~myFactoryConfig( ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
int getNumberOfModules() const { return 1; }
};
class Factory{
Factory(){}
public:
virtual ~Factory(){}
template<class ...Args>
static Factory* create(FactoryConfig<Args...>* pCfg){ return new Factory();}
};
template<class ...Args>
class Factory2{
public:
Factory2(FactoryConfig<Args...>* pCfg){}
virtual ~Factory2(){}
};
int main()
{
// Solution 1
myFactoryConfig* pCfg = new myFactoryConfig(); // <-- why is this not working
// FactoryConfig<ClassA,ClassB>* pCfg = new myFactoryConfig(); // <-- and this works like a charm
Factory* pfac = Factory::create<ClassA,ClassB>(pCfg);
// Solution 2 // Solution 2 is always working
//FactoryConfig<ClassA,ClassB>* pCfg = new myFactoryConfig();
//Factory2<ClassA,ClassB>* pfac = new Factory2<ClassA,ClassB>(pCfg);
delete pfac;
delete pCfg;
return 0;
}
Here is the example at coliru: https://coliru.stacked-crooked.com/a/744c58c7025c1c2f
I'm starting to doubt my c++ knowledge...
Solution without explanation as the previous one was incorrect, stil digging...
You can solve this by making FactoryConfig only inherits FactoryModule<>:
template< class... Args >
class FactoryConfig: public FactoryModuleConfig<Args>...
{
public:
FactoryConfig() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
virtual ~FactoryConfig() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
Compiles fine under clang, possibly a bug in gcc? See g++ c++17 class template argument deduction not working in a very specific case for a vaguely similar example.
I have a templated class pair, and I'd like to write a show function outside of the class to do some fancy couting. When specifying the template type in show explictly, it all works as expected:
#include <iostream>
template <class A_Type>
class pair
{
public:
A_Type a0;
A_Type a1;
};
void show(const pair<double> & p) {
std::cout << p.a0 << std::endl;
std::cout << p.a1 << std::endl;
}
int main() {
pair<double> p;
p.a0 = 1.2;
p.a1 = 1.3;
show(p);
}
I'd like to have show oblivious of the template type though.
Any hints?
You can change show function to:
template<typename DataType>
void show(const pair<DataType> & p) {
std::cout << p.a0 << std::endl;
std::cout << p.a1 << std::endl;
}
Or a better approach (in my opinion) is to make show function member of the class:
template <class A_Type>
class pair {
public:
A_Type a0;
A_Type a1;
void show() const {
std::cout << this->a0 << std::endl;
std::cout << this->a1 << std::endl;
}
};
and then simply:
int main() {
pair<double> p;
p.a0 = 1.2;
p.a1 = 1.3;
p.show();
}
Next code:
#include <typeinfo>
#include <iostream>
struct A
{
A() : _m('a'){ std::cout << "A()" << std::endl; }
void f(){ std::cout << "A::f() " << _m << std::endl; }
char _m;
};
struct B
{
B() : _m('b'){ std::cout << "B()" << std::endl; }
void f(){ std::cout << "B::f() " << _m << std::endl; }
char _m;
};
struct C
{
C() : _m('c'){ std::cout << "C()" << std::endl; }
void f(){ std::cout << "C::f() " << _m << std::endl; }
char _m;
};
template<typename T>
void f(T t = T());
template<typename T>
void f(T t)
{
std::cout << typeid(t).name() << std::endl;
t.f();
}
int main()
{
f<A>();
f<B>();
f<C>();
}
Has this output when using VS2008, VS2010 and VS2012:
A()
struct A
A::f() a
A()
struct B
B::f() a
A()
struct C
C::f() a
Is this a known compiler bug?
Please note that it works as expected in VS2013.
Your compiler might be confused because you have a function template declaration, followed by something that looks like a function template partial specialization. GCC correctly rejects your code.
To be precise, this is the problem:
template<typename T>
void f<T>(T t) { .... }
// ^^^
If you really want to separate declaration and definition, you would need
template<typename T>
void f(T t) { .... }
This would be a well-formed version of your program:
#include <iostream>
#include <typeinfo>
struct A {}; // as before
struct B {}; // as before
struct C {}; // as before
template<typename T>
void f(T t = T())
{
std::cout << typeid( t ).name() << std::endl;
t.f();
}
int main()
{
f<A>();
f<B>();
f<C>();
}