C++ - Separate declaration/definition for template function in template class - c++

I am aware that the syntax for declaring a template class method in a header and defining it in a source file goes as so:
myclass.h
template <typename T>
class MyClass {
public:
void method(T input);
private:
T privVar;
};
myclass.cpp
template <typename T>
void MyClass<T>::method(T input) {
privVar = input;
}
But, what if the method is also a template?
I am adding methods to the basic_string class, and I want to know how to write the implementation for the functions.
MyString.h
template <class _Elem = TCHAR,
class _Traits = std::char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
class String
: public std::basic_string<_Elem, _Traits, _Ax> {
private:
// Types for the conversion operators.
typedef _Elem* _StrTy;
typedef const _Elem* _ConstStrTy;
//...
public:
// Conversion operators so 'String' can easily be
// assigned to a C-String without calling 'c_str()'.
operator _StrTy() const {
return const_cast<_StrTy>(this->c_str());
}
operator _ConstStrTy() const {
return this->c_str();
}
// ... Constructors ...
/*------------ Additional Methods ------------*/
//! Converts a value of the given type to a string.
template <class _ValTy> static String ConvertFrom(_ValTy val);
//! Converts a string to the given type.
template <class _ValTy> static _ValTy ConvertTo(const String& str);
template <class _ValTy> _ValTy ConvertTo(void) const;
//! Checks if a string is empty or is whitespace.
static bool IsNullOrSpace(const String& str);
bool IsNullOrSpace(void) const;
//! Converts a string to all upper-case.
static String ToUpper(String str);
void ToUpper(void);
// ...
};
How could I implement template <class _ValTy> static String ConvertFrom(_ValTy val);? Because now not only do I need to specify the class template, but the function template too. I am betting the code I'm about to write isn't valid, but it should show what I am trying to accomplish:
MyString.cpp
template <class _Elem, class _Traits, class _Ax>
template <class _ValTy>
String<_Elem, _Traits, _Ax> String<_Elem, _Traits, _Ax>::ConvertFrom(_ValTy val) {
// Convert value to String and return it...
}
I am not advanced at all with templates. Not only am I very doubtful that the above is valid, it seems cumbersome to write and not very readable. How would I go about implementing the template methods, and the static template methods which returns its own class type? Because I don't want to define them in the header.

Syntax of definition of template member functions outside of template is like this:
template <class T> struct A
{
template <class X> void f();
};
template<class T> template<class X> void A<T>::f()
{
}
So your code is correct.
Would like to note that defining template members in .cpp is not very useful. In this case you shall explicitly instantiate them with all types you need to use with this template. Or do not use them outside this .cpp which doesn't make sense.

Before I answer your question, let me first say: Don't do this. Extend std::string by using free-functions instead, much like the standard library implements many algorithms. Additionally I'd suggest doing it for ranges rather than strings only but that's more subjective.
Also note that std::string avoids implicit conversions to C-strings not to make your life harder, but to protect your code from a wide variety of obscure bugs that can be caused by unexpected implicit conversions. I would think very long and hard about implementing them. Just think about this: It takes you a few extra moments to type.c_str() once when you write the code, and for the rest of eternity anyone who reads your code will immediately know that it's being used as a C-style string and not as a std::string.
To answer your question, just put the code in the header:
//! Converts a value of the given type to a string.
template <class _ValTy> static String ConvertFrom(_ValTy val)
{
// Code here
}
Finally note that identifiers starting with underscore+capital letter (and many other things starting with _) are reserved for the compiler and thus all bets are off as to your program's functionality.

Your function definition is valid, and it can't be defined outside of the class declaration in a less verbose way. Since you want to put the function definition in a .cpp file you can't take advantage of combining the function definition with the more concise function declaration. By putting the function definition in a .cpp file you will also have to explicitly instantiate all needed specializations of your template class.

Below is an attempt to make an example code for Rost and Josh's answers:
template.hpp
#pragma once
template<class T>
class Add
{
public:
T Addition(T summand1, T summand2);
};
void AddUsing( int summand1, int summand2 );
template.cpp
#include "template.hpp"
#include <iostream>
template<class T>
T Add<T>::Addition(T summand1, T summand2)
{
return summand1 + summand2;
}
void AddUsing( int summand1, int summand2 )
{
std::cout << Add<int>().Addition( summand1, summand2 ) << std::endl;
}
main.cpp
#include "template.hpp"
int main()
{
AddUsing ( 2, 2 );
}

Related

C++, Apply template pattern to function selectively

I have a class that can either be constructed by arguments of "ordinary" types, int, string, etc., or that can be constructed by a couple of different 'special' types invented by a coworker.
The 'special' types have the same signature, but aren't in a parent-child relationship.
So the code I have now looks something like:
class my_nifty_class {
public:
// "ordinary" constructor
template <class T> my_nifty_class(T) {some generic code}
// "special" constructors
my_nifty_class(my_first_clever_class) {
some clever code
}
my_nifty_class(my_second_clever_class) {
the identical clever code
}
In order to avoid duplicating some clever code (and opening myself up to the risk of not always duplicating it right), I would like to replace this with
class my_nifty_class {
public:
// "ordinary" constructor
template <class T> my_nifty_class(T) {some generic code}
// "special" constructors
template <class clever_class> my_nifty_class(clever_class) {
/**** I need template magic somewhere around here ****/
some clever code
}
But -- I don't know the template magic to put in there, or if there is any such magic to be had. I know I could do it if I were declaring classes -- but I'm declaring functions, so I'm kinda stuck.
You want std::enable_if, and you want some compile-time property of your special classes that other classes don't have.
template <class T, class S = std::enable_if_t<!is_my_special_v<T>>>
my_nifty_class(T) {some generic code}
template <class T, class S = std::enable_if_t<is_my_special_v<T>>, bool = true>
my_nifty_class(T) {some special code}
(The dummy template parameter is needed to make the two templates distinct)
Another method is to have just one constructor and use the special selector inside.
template <class T>
my_nifty_class(T) {
if constexpr(is_my_special_v<T>)
some special code
else
some generic code
}
How do you write is_my_special_v? It is just a template with the value of false, with specialisations for your special types with the value of true.
template<class> constexpr bool is_my_special_v = false;
template<> constexpr bool is_my_special_v<MySpecialType1> = true:
// ...
If all your special classes have some member name that is unlikely to occur in non-special classes, you can use that in order to write just one specialisation of is_my_special_v total instead of one per special class. Search for "c++ member detection", lots of material out there.
Finally, if this is the only place where your special types are indeed special, you can skip
is_my_special_v altogether and just check directly.
template <class T>
my_nifty_class(T) {
if constexpr(std::is_same_v<T, MySpecialType1> ||
std::is_same_v<T, MySpecialType2> ...)
some special code
else
some generic code
}
Here is my go at the answer. You will just share a generic constructor for all types. And handle the logic within the constructor using std::is_pod which was introduced in c++11 I believe.
Essentially POD (plain old data) types such as; int, float, double, etc. will be handled by one templated function, and any complex/non-trivial data types will be handled by your other templated function.
class my_nifty_class {
public:
template<class T> handle_pod_type(T value)
{ /* Code to handle POD data types */ }
template<class SpecialType> handle_special_type(SpecialType value)
{ /* Code to handle complex data types */ }
template <class T> my_nifty_class(T value) {
if( std::is_pod<T>::value ) {
handle_pod_type(value);
}
else {
handle_special_type(value);
}
}
}
Also take note of what is_pod is doing and what classifies a POD type in C++11.
I suggest that you can use "tag structures" and class template specializations to solve your problem:
struct TypeA {};
struct TypeB {};
struct TypeC {};
class Class {
public:
template<class T> Class(T val) : Class(typename SelectTag<T>::Type{}, val) {}
private:
struct GenericTag {};
struct BOrCTag {};
template<class T> struct SelectTag { using Type = GenericTag; };
template<class T> Class(GenericTag, T val) { /* do smth */ }
template<class T> Class(BOrCTag, T val) { /* do smth else */ }
};
template<> struct Class::SelectTag<TypeB> { using Type = BOrCTag; };
template<> struct Class::SelectTag<TypeC> { using Type = BOrCTag; };

Initializing a variable dependent on type in template parameter in C++

I have a class with a static const variable that I need to initialize differently depending on the variable type in the template parameter. Is there a way to do this without specialization?
In my header file I have:
template<class Item>
class CircularQueue {
public:
static const Item EMPTY_QUEUE;
...
Attempting to initialize it in the .cpp file:
template<typename Item> const Item CircularQueue<Item>::EMPTY_QUEUE = Item("-999");
I'd like it to initialize to -999 whether it's an int, double, or string. However, in the code above I get a "cast from 'const char' to 'int' loses precision [-fpermissive]" error.
Providing an example of using a separate helper class that can be specialized, instead of having to specialize this entire template class, since you mentioned you'd like to see an example of this approach.
Just declare a separate template class that sets the default value, and specialize it for std::string.
template<class Item> class defaultItem {
public:
static constexpr Item default_value() { return -999; }
};
template<> class defaultItem<std::string> {
public:
static constexpr const char *default_value() { return "-999"; }
};
You don't have to use the constexpr keyword, if your C++ compiler is not of a recent vintage. You can also define the same specialization for a const char *, rather than a std::string, if needed.
Then, your main class simply defines EMPTY_QUEUE as:
template<typename Item>
const Item CircularQueue<Item>::EMPTY_QUEUE =
defaultItem<Item>::default_value();

C++, partial specialization of 2-argument class template: unable to match function definition to an existing declaration

I'm currently implementing a dataset helper class template storing floating point values (Scalar) in a dynamically sized Eigen::Matrix constructed from a vector of different values types (Element) additionally storing a reference to this input vector. Now i want to partially specialize the constructor in the vector value type remaining a template in the scalar type to be explicitly instantiated.
Unfortunately i'm getting "unable to match function definition to an existing declaration" on VS 2010. The code is as simple as:
template <class Scalar, class Element> struct DataSet
{
DataSet(std::vector<Element> const & source);
// several generic member functions here ...
Eigen::Matrix<Scalar, ... > data;
std::vector<Element> const & source;
};
template<class Scalar>
DataSet<Scalar, SomeClass>::DataSet(std::vector<SomeClass> const & input)
{
// special impl for Element==SomeClass ...
}
SomeClass should be automatically be figured out by the compiler, when done right but i tried all meaningful combinations but still getting:
*.cpp(79) C2244 : unable to match function definition to an existing declaration
see declaration of 'DataSet<Scalar, Element>::DataSet'
I was not able to find a matching example by searching the internet yet. Thanks in advance!
EDIT:
To make it more specific, in my real world case i want to be able to define several partial specializations to the constructor with different types for Element e.g:
template<Scalar>
DataSet<Scalar, FirstClass>::DataSet(std::vector<FirstClass> const & first)
: data()
, source(first)
{
// special impl here ...
}
template<Scalar>
DataSet<Scalar, std::shared_ptr<SecondClass> >::DataSet(std::vector<std::shared_ptr<SecondClass> > const & second)
: data()
, source(second)
{
// special impl here ...
}
Redeclaring/specializing the class completely to a certain typename is not desired. Then there is little use to be a template at all. I want the solution as it is, otherwise there might be other strategies to my problem.
FIN:
Since it looks like not being possible to share the type Element between class template and constructor by only specializing the constructor (which is somehow related to an implicit specialization of the class) i removed the reference source from the class template entirely and copied the needed information into a generic container and implemented the constructors via overloads.
When defining your constructor, you didn't explicitly provide both template arguments for its class. That would need to be revised as follows:
template<typename T_Scalar, typename T_Element>
DataSet<T_Scalar, T_Element> // template args for type
::DataSet(std::vector<T_Element> const &input) // but none for constructor
{
// stuff
}
Tangentially related: Unlike methods, template arguments for classes cannot be deduced from constructor calls. That is: until C++17 comes around! woo!
The next stumbling block you faced is that template specialisations do not 'inherit' members from their primary template. It is somewhat intuitive to assume they would, but it's just not so. Until I find an official rationale, I presume it's because template arguments might make certain members totally inapplicable to a specialisation, rendering implicit 'inheritance' problematic. If so, it would've been decided to require full redeclaration / not judged worthwhile to add arcane syntax to specify which primary 'base' members are 'inherited'... when you can simply use real inheritance to ensure they are.
Anyway, what that means is that to get a partial specialisation, you need to declare the whole thing - in this case, the class and its constructor - before you can specialise that constructor's definition. You hadn't declared these ahead of time, so the compiler rightly complained that it couldn't see a declaration.
// Define specialised class
template<typename T_Scalar>
class DataSet<T_Scalar, SomeClass>
{
public:
// Declare its ctor
DataSet(std::vector<SomeClass> const &);
}
// Implement its ctor
template<typename T_Scalar>
DataSet<T_Scalar, SomeClass> // complete template args
::DataSet(std::vector<SomeClass> const &input)
{
// stuff
}
See my working example of an equivalent template class, showing general vs. specialised instantiations.
To add to your original confusion, which is fair! - note that out-of-line definitions can get very complicated indeed if a template class itself contains a template function, because then you need 2 template clauses, e.g.
template<typename TA, typename TB>
class Widget {
template<typename TC>
void accept_gadget(TC &&gadget);
};
template<typename TA, typename TB>
template<typename TC>
Widget<TA, TB>
::accept_gadget(TC &&gadget)
{
/* ... */
}
Something that will help a lot in many contexts, especially including such out-of-line template definitions, is if the proposal to allow namespace class is accepted in a future version. Very sad this didn't make it into C++17... and very odd that it was ever missing in the 1st place!
According to ยง14.7.3.16:
In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.
Still, you can use std::enable_if to partial-specialize your contructor:
template <class Scalar, class Element> struct DataSet
{
template <class T>
DataSet(std::vector<T> const & input, std::enable_if_t<!std::is_same<T, SomeClass>{}> * = nullptr) {
std::cout << "Element\n";
}
template <class T>
DataSet(std::vector<T> const & input, std::enable_if_t<std::is_same<T, SomeClass>{}> * = nullptr) {
std::cout << "SomeClass\n";
}
};
But this way is restrictive:
all your conditions must be exclusives
you'll have to modify the code of your class for every new class you want to handle.
Instead, I'd advise you to use a template helper structure:
DataSet(std::vector<Element> const & input) {
Helper<Element>::do_it(input);
}
that you can specialize as you want:
template <class Element>
struct Helper {
static void do_it(std::vector<Element> const & input) {
std::cout << "General form with Element\n";
}
};
template<>
struct Helper<SomeClass> {
static void do_it(std::vector<SomeClass> const & input) {
std::cout << "SomeClass\n";
}
};
template<>
struct Helper<SomeOtherClass> {
static void do_it(std::vector<SomeOtherClass> const & input) {
std::cout << "SomeOtherClass\n";
}
};
...

Paradigm regarding template class specialization

I'm currently writing a template class for archiving (or serializing) and unarchiving data into/from a binary format. First off, I'm trying to close on what pattern I'll use. I am mostly inclined to using templates because unarchivers don't have an input type for method overloading. For instance, the following example is OK:
Archiver ar;
int i;
archive(ar, i);
But it's counterpart isn't:
Unarchiver unar;
int i;
i = unarchive(unar);
I would like to avoid using the function's name, such as unarchive_int because it would be troublesome when using templates. Say:
template <class T> class SomeClass
{
public:
void doSomething()
{
// Somewhere
T value = unarchive(unar);
}
};
This would make things messy, and as such I rather really use templates for this, whereas the previous expression would be T value = unarchive<T>(ar);. It also seems silly (arguably) to write a global function if either the first or only parameter are always the archiver and unarchiver objects; a template class seems to be in order:
template <class T> class Archiver
{
public:
void archive(T obj);
};
This works, but the archiving method always copies its input object. This is OK with POD data types, but not so much which classes. The solution seems obvious, and instead use a const reference as in void archive(const T & obj), but now it also seems silly to be passing integers, floats, and other PODs by reference. Although I would be happy with this solution, I tried to go a little further and have the object make the distinction instead. My first approach is std::enable_if, while assuming a copy by default (for all non-class members) and provide a class specialization where the archive method gets its input by reference instead. It doesn't work. Here's the code:
template <class T, class E = void>
class Archiver
{
public:
// By default, obj is passed by copy
void archive(T obj);
};
template <class T>
class Archiver<T, typename std::enable_if<std::is_class<T>::value && !std::is_pod<T>::value>::value>
{
public:
// I would expect this to be used instead if is_class<T> && !is_pod<T>
void archive(const T & obj);
};
The problem is that the second declaration is not visible at all to the compiler, and here's proof:
template <> void Archiver<std::uint8_t>::archive(uint8_t obj);
template <> void Archiver<std::string>::archive(const std::string & obj);
The former compiles fine, but the later gives:
out-of-line declaration of 'archive' does not match any declaration in
'Archiver<std::__1::basic_string<char>, void>'
On the other hand, if I get the std::string instead by copy if compiles just fine. I think I know why this happens, the compiler chooses the first template as it's generic enough for both declarations, but then how do I make it choose the more specialized version?
You want std::enable_if<...>::type, not std::enable_if<...>::value.
Here's a full demo:
#include <type_traits>
#include <cstdint>
#include <string>
template <class T, class E = void>
struct Archiver {
void archive(T obj);
};
template <class T>
struct Archiver<T, typename std::enable_if<std::is_class<T>::value && !std::is_pod<T>::value>::type>
{
void archive(const T & obj);
};
template <> void Archiver<std::uint8_t>::archive(std::uint8_t obj);
template <> void Archiver<std::string>::archive(const std::string & obj);
IIUC, the question boils down to how to define a generic template type that is optimized for calling functions.
For this, you can consider boost::call_traits, in particular, param_type:
template<typename T>
void foo(typename boost::call_traits<T>::param_type t);

Providing multiple implementations for templated function tackling a particular type each time

I am writing a comparator for strings. However I want it to work for both strings and char*s.
Something like StringComparer<std::string, std::string> and StringComparer<const char *, const char*>. Of course, inside the implementation for Stringcomparer<const char *, const char *> I will simply do a std::string Stringversion(<pass the const char* here>) for both strings and simply call the Stringcomparer<std::string, std::string>.
How can I write two such templated functions for my Stringcomparer.
I have been looking for this and all I can find everywhere are examples where people have defined a function like this:
template <typename T> foo(T&)
{
//some operation on T that does depends on operators or functions that can handle any //type like sort or cout. basically there are showing that this fucntion can be used to sort //both integer and string vectors or it can cout both integers and floats.
}
Can you please tell me how I can provide multiple variants of my stringcomparer. Surely there are times when people need to write a separate routine handling each type. How is this accomplished.
You can declare a primary function template and the [fully] specialize it for different types, e.g.:
template <typename T> void foo(T&); // primary template declaration
template <> void foo<std::string>(std::string& s) { // specialization for std::string
// ...
}
template <> void foo<char*>(char *&s) { // specialization for char*
// ...
}
Note that the specializations have to match the primary template with the specialized type replaced exactly! In general, I find it easier to specialize class template implementing function objects (i.e., have a function call operator) and delegate to these from a general function template.
You can use template specialisations. Here is a short example.
template <typename T>
void foo(const T& arg)
{
// code
}
// Specialises the function template for char*
template <>
void foo(const char*& arg)
{
// different code
}
EDIT: Oops, specialised for string to start with.