Good evening everyone!
I'm stuck with an itchy problem. Say I have the following code :
#include <iostream>
template <class T>
struct MyTemplate {
int _array[sizeof (T)];
} ;
struct MyStruct {
struct MyNestedStruct {
int foo;
} ;
MyTemplate<MyNestedStruct> _nested;
} ;
int main(int, char **) {
return 0;
}
This example snippet compiles fine. What I would like to do is lift the definition of MyNestedStruct out of MyStruct :
#include <iostream>
template <class T>
struct MyTemplate {
int _array[sizeof (T)];
} ;
struct MyStruct {
struct MyNestedStruct;
MyTemplate<MyNestedStruct> _nested;
} ;
struct MyStruct::MyNestedStruct {
int foo;
} ;
int main(int, char **) {
return 0;
}
Of course this one doesn't compile since I'm requesting the size of a partially declared type (error: invalid application of ‘sizeof’ to incomplete type ‘MyStruct::MyNestedStruct’).
My real use case does need sizeof, but will also use several MyNestedClass-like template parameters in that fashion, each fully declared with constructors and the like. For this reason I don't want MyClass to get bloated. Can I do anything about it, or will I have to resort to an external scope (namespace) to put my "inner" classes in ?
Unless...
struct MyStruct {
#include "MyNestedStruct.h" // Dirty preprocessor to the rescue !
MyTemplate<MyNestedStruct> _nested;
} ;
Ugh.
Essentially we need to defer template instantiation of MyTemplate since that's the one that requires T to be complete. The trick I can see to do that here is to templatize MyStruct.
template <typename T>
struct MyTemplate {
int _array[sizeof(T)];
};
template <typename Dummy = void>
struct MyStruct {
struct MyNestedStruct;
MyTemplate<MyNestedStruct> _nested;
};
template <typename Dummy>
struct MyStruct<Dummy>::MyNestedStruct {
int foo;
};
int main() {}
Now we've deferred the instantiation of MyStruct, but we need to use MyStruct<> instead. If that's unsatisfactory, then just provide a type alias.
#include <iostream>
template <typename T>
struct MyTemplate {
int _array[sizeof(T)];
};
template <typename Dummy = void>
struct MyStructImpl {
struct MyNestedStruct;
MyTemplate<MyNestedStruct> _nested;
};
template <typename Dummy>
struct MyStructImpl<Dummy>::MyNestedStruct {
int foo;
};
using MyStruct = MyStructImpl<>;
int main() {
MyStruct s;
std::cout << sizeof(s._nested._array) << std::endl;
}
Prints 16.
Note: you could also to hide MyStructImpl in a detail namespace or something similar.
Related
I want to change the variable type of member variable when type parameter is the specific type
(ex. int to unsigned char).
The error messages are added in comment.
template <typename T>
class temClass {
private:
template<typename T> // typename : declaration of template parameter 'T' shadows template parameter
struct STR_T {
typedef T T_IF;
};
template<> // <> : error: explicit specialization in non-namespace scope 'class temClass<T>'
struct STR_T<int> { // STR_T<int> : template parameters not deducible in partial specialization
typedef unsigned char T_IF;
};
typedef typename STR_T<T>::T_IF T_DEF;
T_DEF abc;
public:
temClass() { }
~temClass() { }
void showMemSize() {
printf("mem size = %d\n", sizeof(abc));
}
};
and the main function
int main() {
temClass<int> temClassInt;
temClass<unsigned int> temClassUInt;
temClassInt.showMemSize();
temClassUInt.showMemSize();
return 0;
}
The desired result is 1 and 4.
I use eclipse CDT with MinGW GCC. the GCC version is 6.3.0.
i'm so dumb
thanks StoryTeller - Unslander Monica 's comment
just move STR_T to namespace
namespace NS_STR {
template<typename T2>
struct STR_T {
typedef T2 T_IF;
};
template<>
struct STR_T<int> {
typedef unsigned char T_IF;
};
}
template <typename T>
class temClass {
private:
typedef typename NS_STR::STR_T<T>::T_IF T_DEF;
T_DEF abc;
public:
temClass() { }
~temClass() { }
void showMemSize() {
printf("mem size = %d\n", sizeof(abc));
}
};
The result would be 1 and 4
I have a template class of the form:
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::Type Type;
...
private:
void sample(int iteration) {...}
}
I would like to create a specific version of the function sample for the case when ContainerType is a Vector. Where Vector itself is a template class, but I do not know which type of values this Vector holds.
My intuition was to create this in the header file:
template<typename Type>
ConfIntParamStat<Vector<Type> >::sample(int iteration) {
...
}
But it does not compile, and the error from clang is:
error: nested name specifier 'ConfIntParamStat<Vector<Type> >::' for declaration does not refer into a class, class template or class template partial specialization
Is it possible using another syntax ?
If you didnt want to specialize the template and were looking for a member only specialization try the following
#include <iostream>
#include <vector>
using namespace std;
template <typename ContainerType>
class Something {
public:
void do_something(int);
template <typename Which>
struct do_something_implementation {
void operator()() {
cout << "general implementation" << endl;
}
};
template <typename Which>
struct do_something_implementation<vector<Which>> {
void operator()() {
cout << "specialized implementation for vectors" << endl;
}
};
};
template <typename ContainerType>
void Something<ContainerType>::do_something(int) {
do_something_implementation<ContainerType>{}();
}
int main() {
Something<double> something;
something.do_something(1);
return 0;
}
If your intent is to specialize a function, I would just overload the function like so
#include <iostream>
#include <vector>
using namespace std;
template <typename ContainerType>
class Something {
public:
void do_something(int);
template <typename Type>
void do_something(const vector<Type>&);
};
template <typename ContainerType>
void Something<ContainerType>::do_something(int) {
cout << "Called the general method for do_something" << endl;
}
template <typename ContainerType>
template <typename Type>
void Something<ContainerType>::do_something(const vector<Type>&) {
cout << "Called the specialised method" << endl;
}
int main() {
vector<int> vec{1, 2, 3};
Something<double> something;
something.do_something(1);
something.do_something(vec);
return 0;
}
This is mostly why full/explicit function template specializations are not required. Overloading allows for almost the same effects!
Note This is a great article related to your question! http://www.gotw.ca/publications/mill17.htm
You could make use of the overloading mechanism and tag dispatch:
#include <vector>
template <class T>
struct Tag { };
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::value_type Type;
//...
// private:
void sample(int iteration) {
sample_impl(Tag<ContainerType>(), iteration);
}
template <class T>
void sample_impl(Tag<std::vector<T> >, int iteration) {
//if vector
}
template <class T>
void sample_impl(Tag<T>, int iteration) {
//if not a vector
}
};
int main() {
ConfIntParamStat<std::vector<int> > cips;
cips.sample(1);
}
As skypjack mentioned this approach has a little draw when using const. If you are not using c++11 (I suspect you dont because you use > > syntax for nested templates) you could workaround this as follows:
#include <iostream>
#include <vector>
template <class T>
struct Tag { };
template <class T>
struct Decay {
typedef T Type;
};
template <class T>
struct Decay<const T> {
typedef T Type;
};
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::value_type Type;
//...
// private:
void sample(int iteration) {
sample_impl(Tag<typename Decay<ContainerType>::Type>(), iteration);
}
template <class T>
void sample_impl(Tag<std::vector<T> >, int iteration) {
std::cout << "vector specialization" << std::endl;
}
template <class T>
void sample_impl(Tag<T>, int iteration) {
std::cout << "general" << std::endl;
}
};
int main() {
ConfIntParamStat<const std::vector<int> > cips;
cips.sample(1);
}
Another way to approach this is composition.
The act of adding a sample can be thought of as a component of the implementation of the class. If we remove the implementation of adding a sample into this template class, we can then partially specialise only this discrete component.
For example:
#include <vector>
//
// default implementation of the sample component
//
template<class Outer>
struct implements_sample
{
using sample_implementation = implements_sample;
// implements one function
void sample(int iteration) {
// default actions
auto self = static_cast<Outer*>(this);
// do something with self
// e.g. self->_samples.insert(self->_samples.end(), iteration);
}
};
// refactor the container to be composed of component(s)
template<typename ContainerType>
class ConfIntParamStat
: private implements_sample<ConfIntParamStat<ContainerType>>
{
using this_class = ConfIntParamStat<ContainerType>;
public:
// I have added a public interface
void activate_sample(int i) { sample(i); }
// here we give the components rights over this class
private:
friend implements_sample<this_class>;
using this_class::sample_implementation::sample;
ContainerType _samples;
};
//
// now specialise the sample function component for std::vector
//
template<class T, class A>
struct implements_sample<ConfIntParamStat<std::vector<T, A>>>
{
using sample_implementation = implements_sample;
void sample(int iteration) {
auto self = static_cast<ConfIntParamStat<std::vector<T, A>>*>(this);
// do something with self
self->_samples.push_back(iteration);
}
};
int main()
{
ConfIntParamStat< std::vector<int> > cip;
cip.activate_sample(1);
cip.activate_sample(2);
}
I've written a class that has a templated member function, mostly because it takes a std::vector as an argument, however I'm struggling to find a proper way to call it.
class foo(){
// ...
template <typename _t> int bar(const std::vector<_t> *values);
// ...
}
when calling this function later with:
// ...
foo c;
std::vector<int> v(5,100);
c.bar(&v);
// ...
I get the error:
error: no matching function for call to ‘foo::bar(std::vector<int>*)’
c.bar(&v);
Shouldn't foo::bar(std::vector<int>*) conform to the template parameters? Why won't it compile?
Working example:
#include <vector>
class foo{
public:
template <typename _t> int bar(const std::vector<_t> *values) {
return 1;
}
};
int main() {
foo c;
std::vector<int> v(5,100);
c.bar(&v);
}
If you really need it to not to be inline you can:
//from here
#include <vector>
class foo{
public:
template <typename _t> int bar(const std::vector<_t> *values);
};
template <typename _t> int foo::bar(const std::vector<_t> *values) {
return 0;
}
//to here - should be in header file to allow compiler to link it!
int main() {
foo c;
std::vector<int> v(5,100);
c.bar(&v);
}
I am trying to declare an unordered map using templates in c++. However, as I expect the object to be one of the primitive datatypes I don't want to declare a custom class for only one object.
I've tried using :
template <class T> std::unordered_map<int, T> storedObj;
but I keep getting the error: ‘storedObj’ was not declared in this scope
a code snippet is below
#include<iostream>
#include<unordered_map>
#include<deque>
std::deque<int> freeIds;
template <class T> std::unordered_map<int, T> storedObj;
unsigned static int objIdCount=0;
const unsigned long int MAXID = 1000000000;
Can you please tell me what's wrong? Thanks.
You are doing partial template specialisation here (see http://en.cppreference.com/w/cpp/language/partial_specialization). Probably what you had in mind is a typedef-like construction but that doesn't work with templates.
With partial template specialisation you can (partially) re-implement or re-define a templated type.
One way to achieve your goal could be:
template <class T>
class my_unordered_map :
public std::unordered_map<int, T>
{
};
int main( void ) {
my_unordered_map<float> mf;
return 0;
}
Templates are used for compile-time polymorphism. You cannot instantiate a template-based class without specifying an actual datatype for that template.
A basic way to use templates would be:
#include <iostream>
using namespace std;
template <class T>
class MyClass {
T foo;
public:
MyClass(T bar) {
foo = bar;
}
void print() {
cout << foo;
}
};
int main() {
MyClass<int> c(5);
c.print(); // prints 5
return 0;
}
You can achieve what you're trying to do by extending (deriving) the unordered_map class, like this:
#include <iostream>
#include <unordered_map>
using namespace std;
template <class T>
class MyClass: public unordered_map<int, T> {
// optional extra code here
};
int main() {
MyClass<string> cstring;
cstring[0] = "foo";
cout << cstring[0] << "\n"; // prints "foo"
MyClass<double> cdouble;
cdouble[0] = 3.14; // prints 3.14
cout << cdouble[0];
return 0;
}
Suppose we have template class
template <typename T>
class MyTem{
public:
bool is_T_Pointer(){
<...>
}
};
class Cls : MyTem<Cls>{
<...>
};
int main(void){
Cls* classOnHeap = new Cls(); /* T is pointer */
Cls classOnStack; /* T is not pointer */
<...>
}
I know this is a bad example but if someone could help me find out if T is pointer from template class that would be great.
Remember we have inheritance with template of same class as base class.
Doesn't have to be complete implementation, a vague technique will be enough
You should employ partial specialization here:
template<class T>
class A
{
public:
A() {}
};
template<class T>
class A<T*>
{
public:
A(int) {}
};
Then the following will not compile, because compiler is forced to choose pointer version of template and there is no default constructor:
A<char*> a;
this does compile:
A<char> a;
If the compiler supports C++11 use std::is_pointer:
#include <iostream>
#include <type_traits>
template <typename T>
class MyTem
{
public:
static const bool IS_POINTER = std::is_pointer<T>::value;
};
int main()
{
std::cout << MyTem<char*>::IS_POINTER << "\n";
std::cout << MyTem<char>::IS_POINTER << "\n";
return 0;
}
See demo http://ideone.com/Mo394 .