Is it possible to restrict a template? [duplicate] - c++

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ Restrict Template Function
Is it possible to write a C++ template to check for a function's existence?
Is it possible to restrict the types for which a template may be instantiated
(that is, have a compiler error if I use template<type_not_allowed>)?

One way would be to provide no default implementation, and specialize your class template only on those types you wish to allow. For example:
#include <iostream>
using namespace std;
template<class X> class Gizmo
{
public:
Gizmo();
};
template<> Gizmo<int>::Gizmo()
{
}
int main()
{
Gizmo<float> gf; // ERROR: No specialization for Gizmo<float> results in a linking error
}

Make the constructor private in the illegal type:
template<typename T>
class Z
{
public:
Z() {}
};
template<>
class Z<int>
{
private:
Z();
};
Z<float> f; // OK
Z<int> i; // Compile time error.

Related

C++ Template type check std::is_same not working? [duplicate]

This question already has answers here:
Accessing a class member in an if statement using std::is_same
(2 answers)
using std::is_same, why my function still can't work for 2 types
(4 answers)
Closed 4 years ago.
Giving the following code:
#include <string>
template<typename T>
static void parse(T & result)
{
if (std::is_same<T, struct Foo>::value)
{
result.fooValue = 123;
}
else if (std::is_same<T, struct Bar>::value)
{
result.barValue = 456;
}
}
struct Foo { int fooValue; };
struct Bar { int barValue; };
int main()
{
Foo foo;
parse(foo);
Bar bar;
parse(bar);
return 0;
}
This won't compile with error message:
error C2039: 'barValue': is not a member of 'Foo'
error C2039: 'fooValue': is not a member of 'Bar'
What am I doing wrong? can someone please explain to me why when after I pass foo into parse and passing bar it thinks that it's foo and therefore throwing compiler errors. What's the common sense behind this? or in other words, what's the proper why of checking the template type.
Note that I already know about template specialization and instantiation.
Thanks in advance!
When template is instantiated, both branches need to be compiled. Obviously, one of them can't - the specific template type has only one member, but not another.
To solve this problem, you would either need constexpr if from C++17, or, with previous versions, use tag dispatch or SFINAE.

At compilation what happen with class template [duplicate]

This question already has answers here:
How does the compilation of templates work?
(7 answers)
Closed 5 years ago.
what happen when a class template instantiate . i.e i hv a class template and i have created class for int and class for float, so what will happen at compile time( compiler will create 2 seprate class for int and float) or not?
eg :
template <typename T>
class A
{
public:
void foo(T t)
{
//...
};
};
int main()
{
A<int> a;
A<float> b;
}
Yes, the compiler will create two new classes on-the-fly - one for int and one for float.

Template class and forcing certain methods to be implemented by User [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to write a C++ template to check for a function's existence?
I am trying to write a C++ class template. What I want is when this class template is used with user defined classes, I want to force those user defined classes to implemented certain methods say e.g., to_data and from_data. I do not want those for basic C++ primitive datatypes. How do I do this? For example, std::vector give compilation error if the copy constructor of the class is not available.
You can make the methods that must be implemented by user pure virtual functions. If you don't want those for basic C++ primitive datatypes, you can specialize your template for these situations and provide default implementations for these cases.
Simply use the methods in your class template:
template <typename T>
struct Serializer
{
void serialize(T const & t) const { write(t.to_data()); }
void deserialize(T & t) const { t.from_data(read()); }
};
If the types you instantiate the template with have the appropriate member functions, everything will be fine. If they don't, the compiler will trigger an error:
struct Foo
{
int val;
int to_data() const { return val; }
void from_data(int i) { val = i; }
};
struct Bar {};
Serializer<Foo> sf;
sf.serialize(); // OK
Serializer<Bar> sb;
sb.serialize(); // compiler error: Bar has no member function named "to_data"
Note that the compiler error is only triggered when we try to use some functions of the class template. This is because member functions of class templates are only instantiated (compiled, if you will) when you use them. So it is perfectly fine to instantiate Serializer with Bar as long as you don't use the serialize and deserialize member function.
Regarding the second issue, namely how to provide a different behavior for primitive types, you have several solutions. The first one is to specialize your class template for the types you want to handle differently. For instance, the following code specializes Serializer so that it handles int differently:
template <>
struct Serializer<int>
{
void serialize(int i) const { write(i); }
void deserialize(int & i) const { i = read();
};
However, this implies writing a specialization for each particular type, even if some of them are in fact handled in the same way.
A less cumbersome solution would be to use type traits and std::enable_if to select the correct implementation depending on some characteristics of the arguments types (in this case, whether they are primitive or not):
#include <type_traits>
template <typename T, typename Enable = void>
struct Serializer
{
// same as before
};
// Partial specialization for fundamental types
template <typename T>
struct Serializer<T, typename
std::enable_if<std::is_fundamental<T>::value>::type>
{
void serialize(T t) const { write(t); }
void deserialize(T & t) const { t = read(); }
};
Serializer<Foo> sf; // first implementation
Serializer<int> si; // second (specialized) implementation

C++ instantiation of function template with shared_ptrs [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ passing a derived class shared_ptr to a templated function
The compiler has no problems with instantiation when we use pointers.
template <typename T> struct Base{
virtual ~Base() {}
};
template <typename T> struct Der: public Base<T> {
};
template <class T>
void f(Base<T>* b) {}
int main() {
Der<int> x;
f(&x);
}
However if I change f to use shared_ptrs, the compiler cannot find a match.
template <class T>
void f(shared_ptr<Base<T> >b) {}
int main() {
shared_ptr<Der<int> > x(new Der<int>);
f(x);
}
Z.cc: In function ‘int main()’:
Z.cc:45: error: no matching function for call to ‘f(std::tr1::shared_ptr<Der<int> >&)’
Changing x to
shared_ptr<Base<int> > x(new Der<int>);
will also work.
Why is there this difference in behavior?
shared_ptr<Der<int>> is not implicitly convertible to shared_ptr<Base<int>> whereas Der<int>* is implicitly convertible to Base<int>*. C++ doesn't automatically make types instantiated from a template convertible just because the template parameter types happen to be convertible, because that doesn't necessarily make sense and could be dangerous.
http://www2.research.att.com/~bs/bs_faq2.html#conversion

GCC template issues [duplicate]

This question already has an answer here:
Closed 12 years ago.
Possible Duplicate:
problem with template inheritance
This code doesn't compile in GCC:
template <typename T>
struct Base
{
public:
int x;
};
template <typename B>
struct Middle : public B
{
};
template <typename T>
struct Sub : public Middle<Base<T> >
{
public:
void F()
{
x=1; // error: ‘x’ was not declared in this scope
}
};
If either Base or Sub weren't template classes, it wouldn't complain. VC handles it.
Why?
Use this->x = 1; to tell the compiler that x is a (template-) dependent name.
Note: What GCC does ot fine according to the standard, MSVC is just a bit more tolerant.