Reputation: 2100
Edit:
this
and the lack of a ;
at the end of my template class; I had some issues copying and pasting my code, so I copied some code by hand and messed those parts up.Thank you to HugoTeixeira, Matthew Fisher, and user4581301 for your thoughtful responses.
I have the following code in Group.h
:
template <typename T, int N> class Group
{
public:
T values[N];
Group(T args[])
{
for (int i = 0; i < N; i++)
{
values[i] = args[i];
}
}
Group()
{
Group((T[]){0, 0, 0});
}
};
and in main.cpp
, I have this code:
#include "Group.h"
int main()
{
Group<double, 3> * v1 = new Group<double, 3>();
}
When I try to run this code, my IDE gives me the error:
no matching constructor for initialization of 'Group<double, 3>'
I have tried writing this code but minus the template, and it worked fine. What am I doing wrong?
Upvotes: 1
Views: 317
Reputation: 2336
It seems this is an edge cases for the compilers. Various flavors compile for one C++ compiler and not another. The code below works for me on gcc and clang.
template <typename T, int N> class Group
{
public:
T values[N];
Group(T args[])
{
for (int i = 0; i < N; i++)
{
values[i] = args[i];
}
}
Group()
{
Group((T[]){0, 0, 0});
}
};
int main()
{
Group<double, 3> * v1 = new Group<double, 3>();
}
Upvotes: 1
Reputation: 33932
I'm going to head in a different direction and ditch those array casts and other dodgy behavior for a std::initializer_list
(documentation) and a delegated constructor.
template <typename T, size_t N>// replaced int with size_t.
//why allow a negative size?
class Group
{
public:
T values[N];
Group(std::initializer_list<T> list)
{
// may be different sizes
size_t copylen = std::min(list.size(), N);
std::copy(list.begin(),
list.begin()+copylen,
values); // copy all we can
//default initialize remainder, if any
for (size_t i = copylen; i < N; i++)
{
values[i] = T();
}
}
Group():Group{T()} // might be a cleaner way to do this.
// I don't know it.
{
}
/* this may be more efficient. A good compiler can optimize this
down to next-to-nothing
Group()
{
for (size_t i = 0; i < N; i++)
{
values[i] = T();
}
}
*/
};
With the above you can handle a much wider variety of cases. For example,
int main()
{
Group<double, 3> v0; //none
Group<double, 3> v1{1.0}; // too few
Group<double, 3> v3{1.0, 2.0, 3.0};
Group<double, 3> v4{1.0, 2.0, 3.0, 4.0}; // too many
Group<std::string, 3> s2{"A", "B"}; // non-numeric
}
Upvotes: 1
Reputation: 4884
There are a few issues with your code:
Calling another constructor: If you want to call another constructor in C++, you cannot use the this
keyword (like in Java). You have to do it after a colon (aka initializer list), like this:
Group(): Group((T[]){0, 0, 0})
{}
Class definitions end with a semi-colon: In C++, a class definition (templated or not) must end with a semi-colon. You forgot do add it to your code:
class A {
...
}; <<--- end with a semi-colon
Raw pointers: Ideally your code shouldn't use raw pointers. There are smart pointers that can make your code more elegant and easier to maintain. You could, for example, use a std::unique_ptr
or std::shared_ptr
(depending on the case). Here is a simple example in C++14:
auto v1 = std::make_unique<Group<double, 3>>();
Upvotes: 3