Does the constructor not support the specialization of template functions? - c++

I tried to let my class's constructor function became a specialization template function, but I failed the compilation. Does the constructor not support the specialization of template functions? If do, how can I add specialization template function to my class's constructor function?
#include <iostream>
#include <vector>
using namespace std;
class Bignum {
private:
vector<char> vec;
public:
template <class Type> Bignum(const vector<Type> &num) {
vec = num;
}
template <class Type> Bignum(Type &num) {
while (num) {
vec.push_back(num % 10);
num /= 10;
}
}
template <> Bignum(const string &str) {
auto __first = str.rbegin();
auto __last = str.rend();
for (auto i = __first; i <= __last; ++i) {
vec.push_back(*i);
}
}
template <class Type> Bignum(const Type *__first, const Type *__last) {
for (const Type *i = __last; i >= __first; --i) {
vec.push_back(*i);
}
}
template<> Bignum(char *__first, char *__last) {
for (char * i = __last; i >= __first; --i) {
vec.push_back(*i - '0');
}
}
Bignum () {
}
friend ostream& operator << (ostream &os, const Bignum &num) {
auto __first = num.vec.rbegin();
auto __last = num.vec.rend();
for (auto i = __first; i < __last; ++i) {
os << (char)(*i + '0') << ' ';
}
os << (char)(*__last + '0') << endl;
return os;
}
size_t size() const {
return vec.size();
}
const char & at(const size_t &pos) const {
return vec.at(vec.size() - pos);
}
const char & operator [] (const size_t &pos) {
return vec.at(pos);
}
};
int main(int argc, const char * argv[]) {
return 0;
}
I received a compilation error at line 29 which says No function template matches function template specialization 'Bignum'.

As mentioned in the comments, you just need to remove the template <> from the constructors that do not need to be member function templates.
However, it may be beneficial to consider how to accomplish what you may be after in a more generic fashion.
How you actually intend to store the data is confusing, because your implementation does different things (some expect it to be stored in "little-endian" and others expect it in "big-endian" order). In addition, some of your functions expect the data to be stored in the range [0, 9] and others seem to expect data in the range ['0', '9'].
However, none of that is relevant to what I think is the real question, which is about the constructor interface, so I will assume that data is stored as ASCII digits ['0', '9'] and in the order they would be printed as a string - just to pick something.
I would also suggest you use a specific strong type Digit, as the internal representation, which would remove all ambiguity as to the meaning. It would also remove all change of undesired conversions.
It looks like you want to be able to create a BigNum out of anything that can be used to create a vector of char.
This constructor does that. Note that we explicitly disable taking a single integral type, because you can create a vector from one of those, but it does not seem to be what you want, since you have another constructor that appears to take an integral.
template <
typename... ArgTs,
std::enable_if_t<
std::is_constructible_v<std::vector<char>, ArgTs...> &&
not ((sizeof...(ArgTs) == 1) && ... && std::is_integral_v<ArgTs>),
bool> = true>
explicit Bignum(ArgTs && ... args)
: vec(std::forward<ArgTs>(args)...)
{
// If not using a strong type, should at least assert that the
// data you get is what you expect.
assert(vec.size() == std::count_if(
vec.begin(),
vec.end(),
[](unsigned char c){ return std::isdigit(c); }));
}
Then, you can take any unsigned integral type like this (I restricted it to unsigned because it does not look like your code is prepared to handle signed values).
template <
typename T,
std::enable_if_t<
std::is_integral_v<T> && std::is_unsigned_v<T>,
bool> = true>
Bignum(T number)
{
while (number) {
vec.push_back((number % 10) + '0');
number /= 10;
}
std::reverse(vec.begin(), vec.end());
}
And, to accept a string, you do not need a member function template...
Bignum(std::string_view s)
: Bignum(s.begin(), s.end())
{ }
Finally, I'll encourage you to become familiar with the standard algorithms. For example,
friend std::ostream & operator << (std::ostream & os, Bignum const & num)
{
std::copy(num.vec.begin(), num.vec.end(), std::ostream_iterator<char>(os));
return os;
}

Related

Overloading << for a double * or a double[]... how to pass or catch the size?

EDIT:
In addition to the "difficulty" of the size, my overload would have to take precedence over the built-in overload, which prints the address of the first element... as per this, that is not possible, so I am not sure what I want to do is possible, anyway. At least with the proposed syntax below.
Ultimately, I mean to template the overloaded operator as template <class T> std::ostream& operator<<(std::ostream& os, const T* arr) or the like, and explicitly instantiate it for several types (int, char, float, double, etc.), so I have a uniform format.
I usually overload operator<< for vector<T> and other STL containers.
That can easily be done since the objects know their size.
Is there a way to overload operator<< for an array of, say, doubles?
On one hand, it seems one would need to pass the size somehow (it is unknown at compile time).
On the other hand, there seems to be no mechanism for this (AFAIK... I leave it for the knowledgeable to answer).
I.e., I want
int n = 10;
double * pd1 = new double[n];
double pd2[n] = {};
...
cout << pd1 << endl;
cout << pd2 << endl;
I know I can define my custom print, but I want to know if I can work the <<-way.
To get plain old array to with with cout, you can provide an overload like
template <typename T, std::size_t N, std::enable_if_t<!std::is_same_v<char, std::decay_t<T>>, bool> = true>
// SFINAE needed here for char arrays like cout << " "
std::ostream& operator <<(std::ostream& os, T(&array)[N])
{
for (const auto& elem : array)
os << elem << " ";
return os;
}
which allows you to write code like
int main()
{
int arr[10]{1,2,3,4,5,6,7,8,9,10};
std::cout << arr;
}
For an array that you allocate at run time, it gets a little trickier. Pointers in C++ know nothing about the size of the object they point to, or at least as far as the standard is concerned. That means there isn't a portable way to get the size of the array the pointer points to. To get around that, we can leverage std::span from C++20. If you don't have that you can write your own or get an open source version. Doing that gives you an overload like
template <typename T, std::size_t Extent>
std::ostream& operator <<(std::ostream& os, std::span<T, Extent> array)
{
for (const auto& elem : array)
os << elem << " ";
return os;
}
And then you would use it like
int main()
{
int * p_arr = new int[10]{21,22,23,24,25,26,27,28,29,20};
std::cout << std::span{p_arr, 10};
}
It's not exactly the syntax you are looking for, but it only requires you to write the one overload (and potentially span).
The following example allows you to use:
{
int v[5]{1,2,3,4,5};
std::cout << arrayView(v);
int *v2 = new int[5];
std::cout << arrayView(v2, 5);
}
by defining
#include <iostream>
template<class Type>
class ArrayView
{
public:
const Type *const begin, *const end;
};
// creates an ArrayView from a pointer and the number of items
template<class Type>
ArrayView<Type> arrayView(const Type* ptr, size_t items)
{
return { ptr, ptr + items };
}
// creates an ArrayView from a fixed size array
template<class Type, size_t Size>
ArrayView<Type> arrayView(Type (&ptr)[Size])
{
return { ptr, ptr + Size };
}
// outputs an ArrayView
template<class Type>
std::ostream& operator<<(std::ostream& s, ArrayView<Type> v)
{
for (auto it = v.begin; it != v.end; ++it)
s << *it;
return s;
}
int main(int argc, char** argv)
{
double v1[] = { 1, 2, 3, 4 };
double* v2 = new double[5];
for (int i = 0; i < 5; ++i)
v2[i] = i + 10.0;
std::cout << arrayView(v1) << std::endl;
std::cout << arrayView(v2, 5) << std::endl;
return 0;
}
The arrayView template function initializes an instance of the ArrayView template class which carries pointer and size (in the form of begin and end pointer).
For fixed size arrays this is not as efficient as it could be. A more efficient solution would be to create a dedicated template which stores the array size within its type:
template<class Type, size_t Size>
class FixedArrayView
{
public:
const Type* const begin;
};
// creates an ArrayView from a fixed size array
template<class Type, size_t Size>
FixedArrayView<Type, Size> fixedArrayView(Type(&ptr)[Size])
{
return { ptr };
}
// outputs a FixedArrayView
template<class Type, size_t Size>
std::ostream& operator<<(std::ostream& s, FixedArrayView<Type, Size> v)
{
for(size_t i = 0; i < Size; ++i)
s << v.begin[i];
return s;
}
This could also be done without the need of an extra template class
template<class Type, size_t Size>
std::ostream& operator<<(std::ostream& s, Type(&arr)[Size])
{
for (size_t i = 0; i < Size; ++i)
s << arr[i];
return s;
}
which allows you to write
{
int v[5]{1,2,3,4,5};
std::cout << v;
}
But the latest template operator<< has a big problem which strikes you if you , for example, try to output some string literal with std::cout << "abc";
However, there is a solution using SFINAE to make this template not handle "const char" (for which there already is an operator<< defined by <iostream>):
template<class Type, size_t Size, typename std::enable_if<!std::is_same<Type, const char>::value>::type* = nullptr>
std::ostream& operator<<(std::ostream& s, Type(&ptr)[Size])
{
for (size_t i = 0; i < Size; ++i)
s << ptr[i];
return s;
}

C++ Template no match for operator<

I've seen questions similar to this, but haven't found a solution that worked on my problem, so I was hoping I could get some help.
I want to pass a class as an argument to a function with template parameters (For this example I just want it to compile, so nvm that it doesn't make sense with return true in operators). I figured this way in the following code would work:
template<typename T>
class MyClass {
public:
bool operator>(const T&) const {
return true;
}
bool operator<(const T&) const {
return true;
}
};
template<typename T, typename S>
vector<T> between_interval(T* start, T* end, const S& low, const S& high){
vector<T> vec;
for ( ; start != end; start++) {
if (low < *start && *start < high)
vec.push_back(* start);
}
return vec;
}
int main() {
double v1[] = {1.23, 4.56, 7.89, -10, 4};
MyClass<double> k1;
MyClass<double> k2;
vector<double> res = between_interval(v1, v1 + 3, k1, k2);
for (auto x : res)
cout << x << " ";
cout << endl;
}
I get the following error(s):
u4.cpp: In instantiation of ‘std::vector<T> between_interval(T*, T*, const S&, const S&) [with T = double; S = MyClass<double>]’:
u4.cpp:39:55: required from here
u4.cpp:28:36: error: no match for ‘operator<’ (operand types are ‘double’ and ‘const MyClass<double>’)
if (low < *start && *start < high)
I realize passing K1 and K2 won't make sense as it is at the moment, but the compiler doesn't mention this, it complains about not having a match for operator<, so my main question is why? Is it too general with a template argument in operator<? Is there any other way to make the operators work but without using the templates?
Thank you
With
template<typename T>
class MyClass {
public:
bool operator>(const T&) const {
return true;
}
bool operator<(const T&) const {
return true;
}
};
and
MyClass <double> k1;
double d = 4.2;
you might do
k1 < d
k1 > d
but you do
d < k1 (with *start < high)
you have to implement that operator too or change the code to use the provided operator.
Because your operator < is a member function it expects the left hand operand to be of the class type. That is fine for low < *start but in *start < high you have a double as the left hand operand.
You will either need to provide a free function that takes a double as the first parameter or make your class convertible to a double (or T).
Member operators always use the left operand as this and the right operand as the operator argument. That means your comparison operators will only work when the MyClass is on the left of the comparison. The quick fix is to change the line if (low < *start && *start < high) to if (low < *start && high > *start) to put the MyClass instance on the left side of each comparison. The cleaner solution is to provide free operators which take a T on the left side and a MyClass<T> on the right side. For example :
template<typename T>
bool operator>(const T& p_left, const MyClass<T> & p_right) {
return p_right < p_left;
}
template<typename T>
bool operator<(const T& p_left, const MyClass<T> & p_right) {
return p_right > p_left;
}

How to determine if a class implements != operator overloading?

Given the following function:
template <typename T>
static bool equals(const std::vector<T> &a, const std::vector<T> &b) {
if (a.size() != b.size())
return false;
for (size_t i = 0; i < a.size(); ++i)
if (a[i] != b[i]) // Requires that the != operator is supported by the template type.
return false;
return true;
}
how can I determine if the given T overrides the != operator? If someone uses a type without overloading it might end up using a simple binary comparison which might silently lead to wrong results. So I want to ensure only classes that have their own != operator overloading can be used here.
[update 1 - boost 'semi' solution]
I realized that example from my first answer does not work if your class has conversion operator (to type which allows for != comparision), to fix it you can use boost has_not_equal_to type trait. Still its not perfect, as in some cases it generates compilation error instead of giving a value. Those cases are listed in provided link.
[update 2 - concepts solution]
Example with use of concepts:
#include <iostream>
#include <vector>
template<typename T>
concept bool OperatorNotEqual_comparable()
{
return requires (T a, T b) {
{ a.operator!=(b) } -> bool;
};
}
template <OperatorNotEqual_comparable T>
static bool equals(const std::vector<T> &a, const std::vector<T> &b) {
if (a.size() != b.size())
return false;
for (size_t i = 0; i < a.size(); ++i)
if (a[i] != b[i]) // Requires that the != operator is supported by the template type.
return false;
return true;
}
struct sample1{
bool operator!=(const sample1&) const { return true; }
};
struct sample2{
};
struct sample3{
operator void*() { return 0; }
};
int main() {
// Compiles ok!
std::vector<sample1> vec1;
equals(vec1, vec1);
// Fails, which is OK!
//std::vector<sample2> vec2;
//equals(vec2, vec2);
// Fails, which is OK!
//std::vector<sample2*> vec2;
//equals(vec2, vec2);
// Fails, which is OK!
//std::vector<int> vec4;
//equals(vec4, vec4);
// Fails, which is OK!
//std::vector<sample3> vec5;
//equals(vec5, vec5);
}
http://melpon.org/wandbox/permlink/txliKPeMcStc6FhK
[old answer - SFINAE solution, does not check for conversion operator]
You can use SFINAE, and in the near future concepts (they are in gcc 6.0),
#include<iostream>
#include<string>
#include<type_traits>
template<typename T>
class has_not_equal{
template<typename U>
struct null_value{
static U& value;
};
template<typename U>
static std::true_type test(U*,decltype(null_value<U>::value!=null_value<U>::value)* = 0);
static std::false_type test(void*);
public:
typedef decltype(test(static_cast<T*>(0))) type;
static const bool value = type::value;
};
struct sample1{
bool operator!=(const sample1&) { return true; }
};
struct sample2{
};
int main(){
std::cout<<std::boolalpha;
std::cout<<has_not_equal<int>::value<<std::endl;
std::cout<<has_not_equal<std::string>::value<<std::endl;
std::cout<<has_not_equal<sample1>::value<<std::endl;
std::cout<<has_not_equal<sample2>::value<<std::endl;
}
output:
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
true
true
true
false
live
above code is a modified version from this site, it was for operator==, I changed it to operator!=
If T has no operator !=, then the template wont get instantiated for that type, but you will get a (possibly horribly long and unreadable) error message from your compiler. On the other hand, it T has a operator !=, then it should be just fine to use it. There wont be silent wrong result, unless Ts operator != is anyhow broken.
The only other (besides the conversion) case (I can think of) where a binary comparison can happen (has operator!= defined) and lead to silently wrong results is when T is actually a pointer and you expect a "deep comparison".
One could add an overload for vectors containg pointers but that wouldn't cover pointer to array storage.
template <typename T>
static bool equals(const std::vector<T> &a, const std::vector<T> &b)
{
return std::equal(a.begin(), a.end(), b.begin());
}
template <typename T>
static bool equals(const std::vector<T *> &a, const std::vector<T *> &b)
{
return std::equal(a.begin(), a.end(), b.begin()
[](T* ap, T* bp) -> bool { return *ap == *bp; });
}
If you are interested in check whether there is an operator != defined in a class (and it has precisely given signature) you may want this approach (tests taken from marcinj's code):
#include <iostream>
#include <vector>
#include <type_traits>
template <class T, class = void>
struct has_not_equal: std::false_type { };
template <class T>
struct has_not_equal<T, typename std::enable_if<std::is_same<decltype(static_cast<bool (T::*)(const T&)const>(&T::operator!=)), bool (T::*)(const T&)const>::value>::type >: std::true_type { };
struct sample1{
bool operator!=(const sample1&) const { return true; }
};
struct sample2{
};
struct sample3:sample2 {
bool operator!=(const sample2& b) const { return true; }
};
struct sample4:sample2 {
bool operator!=(const sample2& b) const { return true; }
bool operator!=(const sample4& b) const { return true; }
};
int main(){
std::cout<<std::boolalpha;
std::cout<<has_not_equal<int>::value<<std::endl;
std::cout<<has_not_equal<std::string>::value<<std::endl;
std::cout<<has_not_equal<sample1>::value<<std::endl;
std::cout<<has_not_equal<sample2>::value<<std::endl;
std::cout<<has_not_equal<sample3>::value<<std::endl;
std::cout<<has_not_equal<sample4>::value<<std::endl;
}
Output of the program:
false
false
true
false
false
true
You may easily add allowed operator != overloads by adding specialization of the has_not_equal struct...
Even though the title of my question here says I'm looking for a way to determine if the != operator is defined, the real question (as you can read from the description and my comment) was how to ensure that I don't silently get wrong results for a type T which has no != operator defined. The existing answers brought up good points, but the real answer is this:
1) You will get a compiler error on the if (a[i] != b[i]) line if you instantiate the template with a value type array using a type that's missing the != operator override (e.g. std::vector<sample2> from marcinj's answer) or you get hard to understand compiler error if you use std::equal instead. In this case the explicit comparison is much more helpful when looking for a solution.
2) If you have a reference type in the vectors to compare you will at first get no problem at all (since there are comparison operators defined for references, even though they only do a flat comparison via the address values). If you want to ensure that the comparison works as if you had used value types (including deep comparison) then add a specialization for vectors with pointer types, as pointed out by Pixelchemist. However, I cannot get the std::equals variants to compile at the moment.
At the end the solution that works for me is this:
template <typename T>
static bool equals(const std::vector<T> &a, const std::vector<T> &b) {
if (a.size() != b.size())
return false;
for (size_t i = 0; i < a.size(); ++i)
if (a[i] != b[i])
return false;
return true;
}
template <typename T>
static bool equals(const std::vector<T*> &a, const std::vector<T*> &b) {
if (a.size() != b.size())
return false;
for (size_t i = 0; i < a.size(); ++i)
if (*a[i] != *b[i])
return false;
return true;
}
Tested with the sample1/2/3/4 structs from marcinj's answer. It's important to note that the operator overloading must use a value type (operator == (const sample1&)) instead of a reference type.
I have still upvoted all answers that gave me useful information to get the final answer.
If someone uses a type without overloading it might end up using a simple binary comparison which might silently lead to wrong results.
There's not such thing as "binary comparison" in C++. Either your class/struct has operator!= or the template won't be instantiated (and if there are no other candidates then it will be an error).

Using decltype to get an expression's type, without the const

Consider the following program:
int main ()
{
const int e = 10;
for (decltype(e) i{0}; i < e; ++i) {
// do something
}
}
This fails to compile with clang (as well as gcc):
decltype.cpp:5:35: error: read-only variable is not assignable
for (decltype(e) i{0}; i < e; ++i) {
^ ~
Basically, the compiler is assuming that i must be const, since e is.
Is there a way I can use decltype to get the type of e, but removing the const specifier?
I prefer auto i = decltype(e){0}; for this. It's a bit simpler than using type_traits, and I feel it more explicitly specifies the intent that you want a variable initialized to a 0 of e's type.
I've been using Herb's "AAA Style" a lot lately, so it could just be bias on my part.
Use std::remove_const:
#include<type_traits>
...
for (std::remove_const<decltype(e)>::type i{0}; i < e; ++i)
You can also use std::decay:
#include<type_traits>
...
for (std::decay<decltype(e)>::type i{}; i < e; ++i) {
// do something
}
A solution not mentioned yet:
for (decltype(+e) i{0}; i < e; ++i)
Prvalues of primitive type have const stripped; so +e is a prvalue of type int and therefore decltype(+e) is int.
I prefer range-for. Simulate it is very easy.
#include <iostream>
template< typename T >
struct range_t
{
struct iter
{
T operator * ()const noexcept { return n;}
iter& operator ++()noexcept{ ++n; return *this;}
friend
bool operator != (iter const& lhs, iter const& rhs)noexcept
{ return lhs.n != rhs.n;}
T n;
};
iter begin()const noexcept {return {b};}
iter end() const noexcept{ return {e};}
T b, e;
};
template< typename T > range_t<T> range(T b, T e){ return {b,e}; }
int main()
{
const int e = 10;
for( auto i : range(0,e) )
{
std::cout << i << ' ';
}
return 0;
}

c++ overloading operator[] for std::pair

I work a lot with pairs of values: std::pair<int, int> my_pair. Sometimes I need to perform the same operation on both my_pair.first and my_pair.second.
My code would be much smoother if I could do my_pair[j] and loop over j=0,1.
(I am avoiding using arrays because I don't want to bother with allocating memory, and I use pair extensively with other things).
Thus, I would like to define operator[] for std::pair<int, int>.
And I can't get it to work, (I'm not very good with templates and such)...
#include <utility>
#include <stdlib.h>
template <class T1> T1& std::pair<T1, T1>::operator[](const uint &indx) const
{
if (indx == 0)
return first;
else
return second;
};
int main()
{
// ....
return 0;
}
fails to compile. Other variations fail as well.
As far as I can tell, I am following the Stack Overflow operator overloading FAQ, but I guess I am missing something...
you cannot overload operator[] as a non-member
you cannot define a member function which has not been declared in the class definition
you cannot modify the class definition of std::pair
Here's a non-member implementation:
/// #return the nth element in the pair. n must be 0 or 1.
template <class T>
const T& pair_at(const std::pair<T, T>& p, unsigned int n)
{
assert(n == 0 || n == 1 && "Pair index must be 0 or 1!");
return n == 0 ? p.first: p.second;
}
/// #return the nth element in the pair. n must be 0 or 1.
template <class T>
T& pair_at(std::pair<T, T>& p, unsigned int index)
{
assert(index == 0 || index == 1 && "Pair index must be 0 or 1!");
return index == 0 ? p.first: p.second;
}
// usage:
pair<int, int> my_pair(1, 2);
for (int j=0; j < 2; ++j)
++pair_at(my_pair, j);
Note that we need two versions: one for read-only pairs and one for mutable pairs.
Don't be afraid to use non-member functions liberally. As Stroustrup himself said, there is no need to model everything with an object or augment everything through inheritance. If you do want to use classes, prefer composition to inheritance.
You can also do something like this:
/// Applies func to p.first and p.second.
template <class T, class Func>
void for_each_pair(const std::pair<T, T>& p, Func func)
{
func(p.first);
func(p.second);
}
/// Applies func to p.first and p.second.
template <class T, class Func>
void for_each_pair(std::pair<T, T>& p, Func func)
{
func(p.first);
func(p.second);
}
// usage:
pair<int, int> my_pair(1, 2);
for_each_pair(my_pair, [&](int& x){
++x;
});
That isn't too unwieldy to use if you have C++11 lambdas and is at least a bit safer since it has no potential to access out of bounds.
You cannot add functions to an existing class like this. And you certainly can't do it to things in the std namespace.
So you should define your own wrapper class:
class MyPair {
private:
std::pair<int,int> p;
public:
int &operator[](int i) { return (i == 0) ? p[0] : p[1]; }
// etc.
};
You probably should check out Boost.Fusion. You can apply algorithms to sequences(which std::pair is considered a sequence). So for example you can do for_each like this:
std::pair<int, int> my_pair;
for_each(my_pair, [] (int i)
{
cout << i;
});
You can also access the index of the element like this:
int sum = at_c<0>(my_pair) + at_c<1>(my_pair);