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:
When the compiler implicitly instantiates
myclass<int>
when translatingtemplate.cpp
, it does not implicitly instantiatemyclass<int>::doSomething
because, at that point, the function's definition is not yet needed.Even if the compiler were to implicitly instantiate
myclass<int>::doSomething
during the translation oftemplate.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
How to Wait on Multiple Condition Variables in C++11
Forcing Nvidia Gpu Programmatically in Optimus Laptops
Check If a Type Is from a Particular Namespace
Idiomatic Way to Declare C++ Immutable Classes
Should C++ Programmer Avoid Memset
Detect Operator Support with Decltype/Sfinae
How to Enable /Std:C++17 in VS2017 with Cmake
Opencv Orb Not Finding Matches Once Rotation/Scale Invariances Are Introduced
What Does _T Stands for in a Cstring
Static_Assert on Initializer_List::Size()
Columns Auto-Resize to Size of Qtableview
How to Get Cmake to Recognize Pthread on Ubuntu
How to Execute a Piece of Code Only Once
How to Have Polymorphic Containers with Value Semantics in C++
Dynamically Register Constructor Methods in an Abstractfactory at Compile Time Using C++ Templates
When Pass-By-Pointer Is Preferred to Pass-By-Reference in C++