C++ Template Class definition getting error - c++

I am learning C++ templates.I created a template class for addition of two strings
but I'm getting folloing error: Please help me to understand this error.
main.cc:65:52: error: no matching function for call to TheNameHolder<std::basic_string<char> >::TheNameHolder(const char [8], const char [7])
using namespace std;
template <class T>
class TheNameHolder{
T *a, *b;
public:
TheNameHolder(T *first, T *last)
{
a= first;
b= last;
}
T getName();
};
template <class T>
T TheNameHolder<T> :: getName()
{
T returnVal;
returnVal = strcat (returnVal,a);
returnVal = strcat (returnVal, " ");
returnVal = strcat (returnVal, b);
return returnVal;
}
int main()
{
TheNameHolder <string> obj ("Hi", "");
cout << obj.getName ();
return 0;
}

What? No. This isn't what templates are used for
You use strcat on your templated objects (actually, on T*, so on pointers to your object)
strcat accepts only char *. So T has to be char for it to work. If you know T is char, then it isn't a template as you know what it is. (btw - you have another bug that returnval should be T*, and you are using it uninitialized)
You seem to miss the whole concept of templates - which is OK since you are learning.
See - the sentence "I want to use templates to add two strings" is wrong - as you don't have any unknowns! You want to add 2 strings, you know what your type is. It isn't template.
Template would be "I want to add two lists of an unknown type" (then you can't use strcat obviously, nor can you assume your lists are "zero delimited" as that is only true for c style strings).

Your template parameter is std::string, so your constructor
TheNameHolder(T *first, T *last)
expects two pointers to std::string. You are passing it const arrays of char (string literals). It seems to me you can express everything in terms of std::string:
template <class T>
class TheNameHolder{
T a, b;
public:
TheNameHolder(const T& first, const T& last) : a(first), b(last)
{
}
T getName() { return a + " " + b; }
};
int main()
{
TheNameHolder<std::string> obj("Hi", "");
std::cout << obj.getName();
}
Note it isn't completely clear whether you need a class template here. The only advantage of this is that you can also use std::wstring or any other string type that supports initialization from a string literal and the + operator.

As was stated above, this would be the wrong place to use templates since you already know the data type. However, in the case where you may actually wish to "add two lists of an unknown type", you can use template specializations to deal with specific (in this case non-numeric) data types such as strings.
You would specialize this template as follows:
template <>
class TheNameHolder <std::string> {
...
};

Related

How do I best handle conversion into template type from const char *

I have a template function, within which I need to convert a const char * to my template value.
I know for a fact that this const char * was originally read from a ascii text file. My current code looks like this:
template <typename T>
bool Get(T &value, std::string const &query, T const &default)
{
const char* result = DataHandler.GetValue(query);
if (result != NULL)
{
value = static_cast<T>(result); //Here is the issue
return true;
}
value = default
return false;
}
Using this with an int as example i get the error
error C2440: 'static_cast' : cannot convert from 'const char *' to 'int'
Is there a way I can convert the char* to my type T seamlessly, I could not find an answer for this on SO.
In the worst case I can make a case for the 10 types I expect and give an error if not one of these, but I would rather not do it that way if possible.
Is there a way I can convert the char* to my type T seamlessly,
No.
There is no way to make conversion from string to a type automatically work with all types. Such conversion has to be implemented for each class. Typically, it is done by implementing the stream extraction operator >> for std::istream. The built in types such as int and some standard types such as std::string already have such operator. Then you can do for example:
std::istringstream istream(result);
int i;
istream >> i;
Without knowing exactly what you are asking for, using the answer given by #eerorika, here is a generic way to do the conversion:
#include <sstream>
#include <string>
#include <iostream>
template <typename T>
struct DefaultConverter
{
static T Convert(const char *result)
{
std::istringstream istream(result);
T i;
istream >> i;
return i;
}
};
template <typename T, typename Converter = DefaultConverter<T>>
bool Get(T &value, std::string const &query, T const &defaultVal)
{
const char* result = "100";
value = Converter::Convert(result);
return true;
}
int main()
{
int test = 10;
Get(test, "abc123", test);
std::cout << test;
}
The code referring to the DataHandler function is not important to illustrate what the above does.
Basically, the Get function takes an additional argument, namely a conversion template that has an available Convert function that can be called by Get. Note that the default converter simply uses the code as illustrated in the previous answer given by #eerorika.
This gives you the flexibility of providing your own converter that has a Convert function that can do anything customized.
For example:
struct SomeMPEGObject
{
SomeMPEGObject() {}
SomeMPEGObject(const char *) {}
};
struct MPEGConverter
{
static SomeMPEGObject Convert(const char *result)
{
return SomeMPEGObject(result);
}
};
//...
SomeMPEGObject mpeg;
Get<SomeMPEGObject, MPEGConverter>(mpeg, "12345", mpeg);
This will work without changing any code in the Get function.

Can the qsort() function be used with a function template as the comparator?

I am trying to create a function template that receives an array as input and sorts it. In order to sort it, I thought I could use the qsort() function that is included in the header file cstdlib of the C++ standard library. The qsort() function requires a comparator function to be passed as an argument, which in this case needs to be a function template as well.
Unfortunately I simply cannot get it to work. The program compiles successfully if the comparator function is not a function template, but if it is, I get an error that says
no matches converting function ‘compare2’ to type ‘__compar_fn_t {aka int (*)(const void*, const void*)}’
To give you an idea of what I am talking about, here is an example:
#include <cstdlib>
using namespace std;
int compare2(const void *pa, const void *pb)
{
int a = *(const int*) pa;
int b = *(const int*) pb;
if (a > b) {
return -1;
} else if (a < b) {
return 1;
} else {
return 0;
}
}
template <typename type>
void mySort(type* ptr, unsigned int n) //n represents size of array pointed to by ptr
{
qsort(ptr, n, sizeof(ptr[0]), compare2);
return;
}
The above code compiles without any problems, despite the fact that it wouldn't work in practice if an array containing anything other than integers was passed to the mySort() function.
Whereas the following code:
#include <cstdlib>
using namespace std;
template <typename type>
int compare2(const void *pa, const void *pb)
{
type a = *(const type*) pa;
type b = *(const type*) pb;
if (a > b) {
return -1;
} else if (a < b) {
return 1;
} else {
return 0;
}
}
template <typename type>
void mySort(type* ptr, unsigned int n) //n represents size of array pointed to by ptr
{
qsort(ptr, n, sizeof(ptr[0]), compare2);
return;
}
fails to compile with the error that I previously mentioned.
I know that I can easily achieve my goal using other methods (such as using a sorting algorithm inside the mySort() function in the given example), however I really want to get to the bottom of this. Why does qsort() not work with a function template as comparator? Is it due to a mistake I've made or is it simply not possible?
compare2 is a template, not a function. To get a function, a compiler has to instantiate a template. To do that, it should know the template parameters. Typically, they can be deduced from function parameters. In the present case, no deduction is possible, so you have to be explicit by adding <type> to the template name:
qsort(ptr, n, sizeof(ptr[0]), compare2<type>);

How to realise a generic compare ? ( for numbers as well as strings)

Looking for the best method to realize a Class-Method which uses a generic compare.
I have a array of either nubers or a array of strings and then look for either a specific number or a specific string(which is given to my funcion) in that array.
The problem is: If I have strings I need a stringcompare, but stringcompare doesnt work when I have integers or doubles.
Would use template, but im kinda new to that topic.
template <class data_Type> class Foo //data_Type can be int, double or string
{
public:
Foo(data_Type field_x[])
{this.field_x = field_x;}
int get_index(data_Type xy_variable)
{
u = sizeof(field_x) / sizeof(field_x[0]);
for (int i = 0; i < u; i++)
{
if (xy_variable == field_x[i])
{
return i;
}
}
}
private:
data_Type field_x[];
}
If you have a templated class, but need an exception for a specific type, as you do for strings, you can use specialization.
add this outside your class, in the header
template<>
int Foo<std::string>::get_index(std::string xy_variable);
And then you can write a separate implementation that uses your favorite string comparison.
template<>
int Foo<std::string>::get_index(std::string xy_variable) { /*...*/ }

Using "constexpr" to use string literal for template parameter

I have written some code to cast const char* to int by using constexpr and thus I can use a const char* as a template argument. Here is the code:
#include <iostream>
class conststr
{
public:
template<std::size_t N>
constexpr conststr(const char(&STR)[N])
:string(STR), size(N-1)
{}
constexpr conststr(const char* STR, std::size_t N)
:string(STR), size(N)
{}
constexpr char operator[](std::size_t n)
{
return n < size ? string[n] : 0;
}
constexpr std::size_t get_size()
{
return size;
}
constexpr const char* get_string()
{
return string;
}
//This method is related with Fowler–Noll–Vo hash function
constexpr unsigned hash(int n=0, unsigned h=2166136261)
{
return n == size ? h : hash(n+1,(h * 16777619) ^ (string[n]));
}
private:
const char* string;
std::size_t size;
};
// output function that requires a compile-time constant, for testing
template<int N> struct OUT
{
OUT() { std::cout << N << '\n'; }
};
int constexpr operator "" _const(const char* str, size_t sz)
{
return conststr(str,sz).hash();
}
int main()
{
OUT<"A dummy string"_const> out;
OUT<"A very long template parameter as a const char*"_const> out2;
}
In this example code, type of out is OUT<1494474505> and type of out2 is OUT<106227495>. Magic behind this code is conststr::hash() it is a constexpr recursion that uses FNV Hash function. And thus it creates an integral hash for const char* which is hopefully a unique one.
I have some questions about this method:
Is this a safe approach to use? Or can this approach be an evil in a specific use?
Can you write a better hash function that creates different integer for each string without being limited to a number of chars? (in my method, the length is long enough)
Can you write a code that implicitly casts const char* to int constexpr via conststr and thus we will not need aesthetically ugly (and also time consumer) _const user-defined string literal? For example OUT<"String"> will be legal (and cast "String" to integer).
Any help will be appreciated, thanks a lot.
Although your method is very interesting, it is not really a way to pass a string literal as a template argument. In fact, it is a generator of template argument based on string literal, which is not the same: you cannot retrieve string from hashed_string... It kinda defeats the whole interest of string literals in templates.
EDIT : the following was right when the hash used was the weighted sum of the letters, which is not the case after the edit of the OP.
You can also have problems with your hash function, as stated by mitchnull's answer. This may be another big problem with your method, the collisions. For example:
// Both outputs 3721
OUT<"0 silent"_const> out;
OUT<"7 listen"_const> out2;
As far as I know, you cannot pass a string literal in a template argument straightforwardly in the current standard. However, you can "fake" it. Here's what I use in general:
struct string_holder //
{ // All of this can be heavily optimized by
static const char* asString() // the compiler. It is also easy to generate
{ // with a macro.
return "Hello world!"; //
} //
}; //
Then, I pass the "fake string literal" via a type argument:
template<typename str>
struct out
{
out()
{
std::cout << str::asString() << "\n";
}
};
EDIT2: you said in the comments you used this to distinguish between several specializations of a class template. The method you showed is valid for that, but you can also use tags:
// tags
struct myTag {};
struct Long {};
struct Float {};
// class template
template<typename tag>
struct Integer
{
// ...
};
template<> struct Integer<Long> { /* ... */ };
// use
Integer<Long> ...; // those are 2
Integer<Float> ...; // different types
Here is the pattern that I am using for template const string parameters.
class F {
static constexpr const char conststr[]= "some const string";
TemplateObject<conststr> instance;
};
see :
https://stackoverflow.com/a/18031951/782168

Overwrite Cast Operator in C++

As a C++ beginner I want to write some simple type casts. It there a way to create casting logic which can be used in the type new = (type)old format with the prefix parentheses?
string Text = "Hello";
char* Chars = "Goodbye";
int Integer = 42;
string Message = Text + (string)Integer + (string)Chars + "!";
I'd like to stick with this syntax if possible. For example the string cast of boost int Number = boost::lexical_cast<int>("Hello World") has an unattractive long syntax.
Just use a normal function that you overload for different types:
std::string str(int i) {
return "an integer";
}
std::string str(char* s) {
return std::string(s);
}
Then use if not like a cast, but as a normal function call:
string Message = Text + str(Integer) + str(Chars) + "!";
It's the most common thing in C++ to cast using a NAME<TYPE>(ARGUMENT) syntax, like in static_cast<int>(char). It makes sense to extend this the way boost does.
However, if you want to convert non-primitive types, you can use non-explicit constructors with a single argument and the cast operator.
class MyType {
public:
MyType(int); // cast from int
operator int() const; // cast to int
};
This is not possible if you are dealing with already existing types.
You cannot change the behaviour of the C-style cast. C++ will make up its mind how to interpret such a cast.
You could however come up with an intermediate type that shortens the syntax:
template <typename From>
struct Cast {
From from;
Cast(From const& from) : from(from) {}
template <typename To>
operator To() const {
return convert(from,To());
}
};
template <typename From>
Cast<From> cast(From const& from) {
return Cast<From>(from);
};
std::string convert(int, std::string const&);
This would allow you to convert things explicitly but without stating how exactly:
int i = 7;
std::string s = cast(i);