Template Function Inside Template Class

Template function inside template class

Write this:

template <class T>
template <class U>
void MyClass<T>::foo() { /* ... */ }

Instantiating nested template function in template class

You can do it with this:

template int A<int>::b<short>(short r);

C++ specialization of template function inside template class

So, I'm taking a different approach to answering your question. I'm going to start from something that sort of does what you want, and works. And then maybe we can figure out how to permute it into something closer to what you really want:

#include <string>
#include <iostream>

int getIntThing(const ::std::string ¶m);

template <typename returnT>
returnT getThingFree(const ::std::string ¶m);

template <>
int getThingFree<int>(const ::std::string ¶m)
{
return getIntThing(param);
}

// More specialized definitions of getAThing() for other types/classes
// go here...

template <class c1> class X {
public:
template<typename returnT> returnT getAThing(std::string param);
static std::string getName();
private:
c1 theData;
};

// This works ok...
template <class c1> std::string X<c1>::getName() {
return c1::getName();
}

// This also works, but it would be nice if I could explicitly specialize
// this instead of having to explicitly specialize getThingFree.
template <class c1>
template <class RT>
RT X<c1>::getAThing(std::string param) {
// Some function that crunches on param and returns an RT.
// Gosh, wouldn't it be nice if I didn't have to redirect through
// this free function?
return getThingFree<RT>(param);
}

class Y {
public:
static std::string getName() { return "Y"; }
};

int main(int argc, char* argv[])
{
using ::std::cout;
X<Y> tester;
int anIntThing = tester.getAThing<int>(std::string("param"));
cout << "Name: " << tester.getName() << '\n';
cout << "An int thing: " << anIntThing << '\n';
}

Here is another idea that sort of works, and isn't exactly what you want, but is closer. I think you've thought of it yourself. It's also rather ugly in the way it uses type deduction.

#include <string>
#include <iostream>

template <class c1> class X;

int getIntThing(const ::std::string ¶m)
{
return param.size();
}

// You can partially specialize this, but only for the class, or the
// class and return type. You cannot partially specialize this for
// just the return type. OTOH, specializations will be able to access
// private or protected members of X<c1> as this class is declared a
// friend.
template <class c1>
class friendlyGetThing {
public:
template <typename return_t>
static return_t getThing(X<c1> &xthis, const ::std::string ¶m,
return_t *);
};

// This can be partially specialized on either class, return type, or
// both, but it cannot be declared a friend, so will have no access to
// private or protected members of X<c1>.
template <class c1, typename return_t>
class getThingFunctor {
public:
typedef return_t r_t;

return_t operator()(X<c1> &xthis, const ::std::string ¶m) {
return_t *fred = 0;
return friendlyGetThing<c1>::getThing(xthis, param, fred);
}
};

template <class c1> class X {
public:
friend class friendlyGetThing<c1>;

template<typename returnT> returnT getAThing(std::string param) {
return getThingFunctor<c1, returnT>()(*this, param);
}
static std::string getName();
private:
c1 theData;
};

// This works ok...
template <class c1> std::string X<c1>::getName() {
return c1::getName();
}

class Y {
public:
static std::string getName() { return "Y"; }
};

template <class c1>
class getThingFunctor<c1, int> {
public:
int operator()(X<c1> &xthis, const ::std::string ¶m) {
return getIntThing(param);
}
};

// More specialized definitions of getAThingFunctor for other types/classes
// go here...

int main(int argc, char* argv[])
{
using ::std::cout;
X<Y> tester;
int anIntThing = tester.getAThing<int>(std::string("param"));
cout << "Name: " << tester.getName() << '\n';
cout << "An int thing: " << anIntThing << '\n';
}

I would recommend declaring getThingFunctor and friendlyGetThing in a semi-private utility namespace.

Using template methods inside template classes

Why is it expecting Struct1

Because that is the type it was told to use.

Given the template:

template<typename Type>
class GenericClass
{
private:
Type Identifier;

public:
void setIdentifier(Type Param);
Type getIdentifier();
};

The instantiation with type Struct1 (GenericClass<Struct1>) generates the following implementation:

// Just for illustration
class GenericClassStruct1
{
private:
Struct1 Identifier;

public:
void setIdentifier(Struct1 Param);
Struct1 getIdentifier();
};

The above class has replaced all occurrences of Type with Struct1. Now, it should be easy to see why calling setIdentifier expects a Struct1 and not an int.

how do I format it so I can modify the properties in any struct

There is more than one way to do this. What is the "right" way will depend on the constraints of your problem but following example shows one way.

Example

Working Example

#include <iostream>

// Declared but not defined, specializations will provide definitions
template<typename T>
struct GenericTypeTraits;

template<typename T>
class Generic
{
public:
using IdType = typename GenericTypeTraits<T>::IdType;

void setIdentifier(IdType id)
{
mType.mIdentifier = id;
}

IdType getIdentifier() const
{
return mType.mIdentifier;
}

private:
T mType;
};

class Type1
{
public:
int mIdentifier;
};

template<>
struct GenericTypeTraits<Type1>
{
using IdType = int;
};

class Type2
{
public:
std::string mIdentifier;
};

template<>
struct GenericTypeTraits<Type2>
{
using IdType = std::string;
};

int main()
{
Generic<Type1> t1[5];
t1[0].setIdentifier(3);
std::cout << t1[0].getIdentifier() << "\n";

Generic<Type2> t2[5];
t2[0].setIdentifier("3");
std::cout << t2[0].getIdentifier() << "\n";

return 0;
}

Output

3
3

How to define template function within template class in *.inl file

Here's your definition:

template <typename T1, typename T2>
template <typename E>
void SomeClass<T1, T2>::extraTypedMethod(E & e)
{
}

Definition of a template function inside .cpp file is not working even though I am instantiating a dummy object in .cpp file

Your first question was why writing:

template<> class myclass <int>;

causes an undefined reference error. The answer is that template<> declares an explicit specialization: it's saying that there is a special definition of myclass<int>::doSomething that takes the place of the generic definition earlier in the file. However, the definition of the specialization is not provided. Therefore, no definition of myclass<int>::doSomething is emitted when template.cpp is translated.

Your second question was why replacing the explicit instantiation with:

myclass <int> obj;

in template.cpp did not cause myClass<int>::doSomething to be emitted from that translation unit. The answer is twofold:

  1. When the compiler implicitly instantiates myclass<int> when translating template.cpp, it does not implicitly instantiate myclass<int>::doSomething because, at that point, the function's definition is not yet needed.

  2. Even if the compiler were to implicitly instantiate myclass<int>::doSomething during the translation of template.cpp, that implicit instantiation is NOT guaranteed to make that instantiated definition available to other translation units. (The compiler may, in effect, generate it with internal linkage.)

See C++17 [temp]/7

A function template, member function of a class template, variable template, or static data member of a
class template shall be defined in every translation unit in which it is implicitly instantiated (17.7.1) unless
the corresponding specialization is explicitly instantiated (17.7.2) in some translation unit; no diagnostic is
required.

What this is saying is that if you need to call a function template from translation unit 1, but you only want to define that function template in translation unit 2, then translation unit 2 must explicitly instantiate the function template with the desired arguments. An implicit instantiation doesn't count.

(Note that the explicit instantiation of myclass<int> will also implicitly instantiate the definitions of all of myclass<int>'s member functions.)

Function return type for template class inside template class

As the compile error suggests, use typename

template <typename T>
template <typename D>
typename C<T>::N *C<T>::fun(D d) {
}

template friend functions of template class

The simplest option is to define the friend within the class:

template<class T>
class MyVar
{
int x;

friend void printVar(const MyVar & var) {
std::cout << var.x << std::endl;
}
friend void scanVar(MyVar & var) {
std::cin >> var.x;
}
};

The downside is that the functions can only be called through argument-dependent lookup. That's not a problem in your example, but might be a problem if they don't have a suitable argument, or you want to specify the name without calling it.

If you want a separate definition, then the template will have to be declared before the class definition (so it's available for a friend declaration), but defined afterwards (so it can access the class members). The class will also have to be declared before the function. This is a bit messy, so I'll only show one of the two functions:

template <typename T> class MyVar;
template <typename T> void printVar(const MyVar<T> & var);

template<class T>
class MyVar
{
int x;

friend void printVar<T>(const MyVar<T> & var);
};

template <typename T> void printVar(const MyVar<T> & var) {
std::cout << var.x << std::endl;
}

Template class with template function

The compiler already tells you the answer. The class C is a template with one parameter, and the member function f is a template member function, and you have to define it in the same way:

template <class X>
template <class Y>
void C<X>::f(Y y)
{
// Something.
}

If you define the function at the declaration site, you'll implicitly declare it inline; that's about the only difference practically. There may be stylistic considerations, of course, e.g. never to put function definitions inside class definitions.

As you rightly observe, you will still have to provide the definition in the header file, since you will need to instantiate the template whenever you use it, and thus you need access to all the definitions.

Defining a templated friend function inside a template class

The only place you declare the template function is inside the class; it is not "visible" in the enclosing namespace and hence not available for normal lookup, only for argument dependent lookup.

You need to declare (and define) it outside the class for the function to be found, and to declare it as a friend function (as you noted).

From cppreference

A name first declared in a friend declaration within class or class template X becomes a member of the innermost enclosing namespace of X, but is not accessible for lookup (except argument-dependent lookup that considers X) unless a matching declaration at the namespace scope is provided...



Related Topics



Leave a reply



Submit