Recently I stumbled upon such piece of code:
template <typename Ta> template <typename Tb>
void SomeClass<Ta>::Function() {}
There is template function, but it has strange syntax, which I don't really understand. What does it do? Is it anwhere near template<template<typename Ta>>?
I have never met such syntax, and I am confused.
Sometimes all it needs is a complete example:
template <typename Ta>
struct SomeClass {
template <typename Tb>
void Function();
};
template <typename Ta> template <typename Tb>
void SomeClass<Ta>::Function() {}
int main() {
SomeClass<int> sc;
sc.Function<double>();
}
It is a definition of a method template of a class template.
Sometimes You need compatibility with compatible objects while writing templates. For example int and double are compatible with each other. But if you have a template class objects lets say Something<int> and Something<double> and you try to assign them it will not work. You do this especially while writing copy or move assignment operators or constructors. Let suppose we have an a class template Something.
template <typename T>
class Something {
public:
Something();
Something(const Something& obj) : data(obj.data)
{
};
private:
T data;
};
int main(){
Something<int> number;
Something<double> double_number;
Something<double> newObj(number);
}
if you try to do this, it will not compile.
To make it compile you make template of your copy constructor as in this case. To make it compile you have to something like this.
template <typename T>
class Something {
public:
Something();
template<typename E>
Something(const Something<E>& obj);
T get_data() const{
return data;
}
private:
T data;
};
template<typename T>
template <typename E>
Something<T>::Something(const Something<E>& src): data(src.get_data()){
}
int main(){
Something<int> number;
Something<double> double_number;
Something<double> newObj(number);
}
Note that we are calling the public method to assign data to this object because Something<int> and Something<double> both are of different types.
Related
I try to create a templated class, which saves the template argument as a member variable (msg_).
Now the input of the class should allow normal types like int and shared_ptr<int>.
template <typename T>
class Foo {
public:
Foo<T>() {};
private:
T msg_;
};
My problem is if the class gets initialized with shared_ptr<int>, the shared_ptr has to get initialized:
this->msg_ = std::make_shared<T*>();
I tried to solve it like this:
Foo<T>() {
if (std::is_pointer<T>::value) {
this->msg_ = std::make_shared<T*>();
}
};
, but the problem is that is has to be solved on compile time. Otherwise I can not compile.
Do you know any patterns, which solve this issue?
Thank you! and
Best regards
Fabian
You might have specialization
template <typename T>
class Foo {
public:
Foo() {}
private:
T msg_;
};
template <typename T>
class Foo<std::shared_ptr<T>>
{
public:
Foo() : msg_(std::make_shared<T>()) {}
private:
std::shared_ptr<T> msg_;
};
or create function to initialize (with overload)
template <typename> struct tag{};
template <typename T>
T foo_default_init(tag<T>) { return {}; }
template <typename T>
std::shared_ptr<T> foo_default_init(tag<std::shared_ptr<T>>)
{
return std::make_shared<T>();
}
template <typename T>
class Foo {
public:
Foo() : msg_(foo_default_init(tag<T>{})){}
private:
T msg_;
};
I have a class like:
tempate<class TReturn>
struct MyClass {
template<class T>
TReturn doSomething(const T &t) {
// Do something
return someValue;
}
};
Now TReturn can be anything even void but in case it is void I want no return statement at the end and some minor different code in the function. What I want is a different function body depending on the return type. I'm using C++11 so if constexpr is not possible for me. Is there any way to to this in plain C++11?
You can provide a specialization of your class for void:
tempate<>
struct MyClass<void> {
template<class T>
void doSomething(const T &t) {
// Do something else
}
};
If the class is in fact larger than you show and you want to specialize just this one function and not the whole thing, then a) it was probably unwise to make TReturn a parameter of the class when only a small part of the class depends on it, but b) there are ways to simulate that. E.g. you could sort of "partially specialize" the method by indirecting through a helper class (unlike function templates, class templates allow partial specialization). Something like this:
tempate<class TReturn> struct MyClass;
namespace internal {
template <typename TReturn, typename T>
class MyClassDoSomethingHelper {
static TReturn Run(MyClass<TReturn>* that, const T &t) {
// do something
return someValue;
}
};
template <typename T>
class MyClassDoSomethingHelper<void, T> {
static void Run(MyClass<void>* that, const T &t) {
// do something else
}
};
} // namespace internal
tempate<class TReturn>
struct MyClass {
template<class T>
TReturn doSomething(const T &t) {
return internal::MyClassDoSomethingHelper<TReturn, T>::Run(this, t);
}
};
I need to define a friend function for the templated class. The function has
return type that is a member type of the class. Now, I can not declare it beforehand, since the the return type is not known at the time. Something like this
template<class T> class A;
//This doesn't work: error: need ‘typename’ before...
template<class T> A<T>::member_type fcn(A<T>::member_type);
//This doesn't work: error: template declaration of ‘typename...
template<class T> typename A<T>::member_type fcn(A<T>::member_type);
template<class T>
class A{
public:
typedef int member_type;
friend member_type fcn<T>(member_type);
};
How do I do this?
I managed to compile that code on g++ using :
template<class T> typename A<T>::member_type fcn(typename A<T>::member_type);
(Thus a second 'typename' was required)
You need to say typename also in the argument:
template <class T>
typename A<T>::member_type fcn(typename A<T>::member_type);
// ^^^^^^^^
Otherwise there's no problem with your code, as long as all the template definitions appear before the function template is first instantiated.
It seems that in your particular example nothing in fcn function actually depends on class A. It doesn't even need to access any of the A's methods/fields, neither public nor protected/private. So it doesn't make sense. It would have made some sense otherwise, but at any rate it seems like it is worth re-thinking your problem and come up with a cleaner solution that does not need a hack like that. If, after a deep thought, you still believe you need it, you can do something like this:
#include <cstdio>
template<typename T> typename T::member_type fcn(const T & v) {
return v.value_;
}
template<class T>
class A {
public:
typedef T member_type;
friend member_type fcn< A<T> >(const A<T> &);
A() : value_(1986) {}
private:
T value_;
};
int main()
{
A<int> a;
printf("The value is: %d\n", fcn(a));
}
Notable thing in the above example is that you need to de-couple a cross dependency and make your free-function not depend on a declaration of class A. If you still feel like you need that coupling, the following code works, too:
#include <cstdio>
template <typename T>
class A;
template <typename T> typename A<T>::member_type fcn(const A<T> & v) {
return v.value_;
}
template <typename T>
class A {
public:
typedef int member_type;
friend member_type fcn<T>(const A<T> &);
A() : value_(1986) {}
private:
member_type value_;
};
int main()
{
A<void> a;
printf("The value is: %d\n", fcn(a));
}
Hope it helps. Good Luck!
This may by now be redundant with someone else's answer, but here's a complete, testable solution. The final function definition is a template specialization of fcn, which will produce a compiler error indicating that A<double>::x is not accessible from fcn<int>, but A<int>::x is accessible.
template<class T> class A;
template <typename U>
typename A<U>::member_type fcn(typename A<U>::member_type);
template<class T>
class A {
int x;
public:
typedef int member_type;
friend typename A<T>::member_type fcn<T>(typename A<T>::member_type);
};
template<>
int fcn<int>(int x)
{
A<int> i;
A<double> d;
i.x = 0; // permitted
d.x = 0; // forbidden
return 0;
}
I have the following simplified code:
template <class T>
class A
{
public:
template <class U>
static U foo(T* p)
{
p;
return U();
}
};
class B
{
/*template <class T>
template <class U>
friend U A<T>::foo<U>(T*);*/
friend B A<B>::foo<B>(B*);
B()
{}
public:
};
...
A<B>::foo<B>(nullptr);
And it works quite well. But the things that I've not managed to do are commented:
/*template <class T>
template <class U>
friend U A<T>::foo<U>(T*);*/
I don't know what the syntax I should use to make it works. So I need to generalize my friend declaration to all possible types. I've tried quite a few variants of syntax but had no success. Could some one point me out what should I write instead of my commented code to make it works?
Thanks!
What you're looking for is
template <class T>
template <class U>
friend U A<T>::foo(T*);
The following works on IdeOne.com
#include <iostream>
template <class T>
class A
{
public:
template <class U>
static U foo(T* p)
{
p;
return U();
}
};
class B
{
template <class T>
template <class U>
friend U A<T>::foo(T*);
B() {}
public:
void hello() const
{
std::cout << "I'm a B!" << std::endl;
}
};
int main(int, char*[])
{
A<B>::foo<B>(NULL).hello();
}
I will agree with the othe commenters, friends and templates simply don't mix, at least not in any consistent way with across a range of compilers. The standard probably states exactly what should work, though that will likely not help you. Sad but true.
Friend is often not a good idea anyhow, it might be better to consider how to write the code without friendship, or use the "poor man's friend" of a public method with a comment indicating it is not for general use.
I'm writing a set of C++ parameterized classes and I'm interested in some of them behaving similarly to pointers. In particular, I want to be able to create an object with a constant template parameter from an object with a non-constant template parameter, but not the other way around. This sample code should clarify my intentions:
int main() {
myClass<int> mc_int;
myClass<const int> mc_const_int;
myClass<const int> mc1(mc_const_int); // This should compile.
myClass<int> mc2(mc_int); // This should compile.
myClass<const int> mc3(mc_int); // This should compile.
myClass<int> mc4(mc_const_int); // This should NOT compile.
}
I have been able to achieve this particular behavior by creating the next class hierarchy (simplified for readability):
template <typename T>
class Base {
// ...
protected:
template <typename U>
Base(const Base<U> &obj): _elem(obj._elem) {}
private:
T _elem;
friend class Base<const T>;
};
template <typename T>
class myClass: public Base<T> {
// ...
public:
template <typename U>
myClass(const myClass<U> &obj): Base<const U>(obj) {}
};
And it works as expected, but I'm not entirely satisfied with this design because I can only detect a non-constant template parameter from the constructor, but not from any other member function.
If I wanted, for example, to create a container class with an addAll() method, I would like to be able to do this:
int main() {
Container<int> c_int;
c_int.add(new int(1));
c_int.add(new int(2));
c_int.add(new int(3));
Container<const int> c_const_int;
c_const_int.addAll(c_int); // This should compile.
c_int.addAll(c_const_int); // This should NOT compile.
}
But I don't know how to achieve the previous behavior. Does anyone have ideas for an alternate design to achieve what I'm trying to do? Does anyone know of a link where this problem is discussed in more depth?
Thanks in advance.
One way to do this is via partial template specialisation. You should define the class for non-const types as you usually would:
template <typename T>
struct MyClass {
void f(T&);
};
Then define a specialisation
template <typename T>
struct MyClass<T const> {
void f(T&);
void f(T const&);
};
Unfortunately, this leads to code duplication, but it should allow you to do what you want. Naturally, you can have the functions take MyClass<T>& and MyClass<T const>&, too.
I'm kind of understand the question a bit. You probably can use template specialization.
template <typename T>
class container
{
public:
template<typename U>
void addAll(const container<U>& b ){}
private:
template<>
void addAll(const container<int>&b); //No implementation
};
container<int> b;
....
container<const int> a;
a.addAll(b) ; //Give a link error, I can't understand why vc2010 compile and run this line though
One possibility is using member function templates, enabling them so as to achieve the combinations you want.
#include <utility>
template <class T, class U>
struct const_convertible;
template <class T>
struct const_convertible<T, T>: std::true_type {};
template <class T>
struct const_convertible<T, const T>: std::true_type {};
template <class T>
struct const_convertible<const T, T>: std::false_type {};
template <class T>
class X
{
public:
X() {}
X(const X&) {} //copy constructor
//conversion constructor as needed
template <class U>
X(const X<U>&, typename std::enable_if<const_convertible<U, T>::value, void>::type* = 0)
{}
template <class U>
typename std::enable_if<const_convertible<U, T>::value, void>::type f(X<U>) {}
};
int main()
{
X<int> mut;
X<const int> con;
X<int> a(mut);
//X<int> b(con);
X<const int> c(mut);
X<const int> d(con);
mut.f(mut);
//mut.f(con);
con.f(mut);
con.f(con);
//X<double> doub;
//doub.f(mut);
}