I hate to ask such a general question, but the following code is a exercise in explicit template specialization. I keep getting the error:
c:\users\***\documents\visual studio 2010\projects\template array\template array\array.h(49): error C2910: 'Array::{ctor}' : cannot be explicitly specialized
#ifndef ARRAY_H
#define ARRAY_H
template <typename t>`
class Array
{
public:
Array(int);
int getSize()
{
return size;
}
void setSize(int s)
{
size = s;
}
void setArray(int place, t value)
{
myArray[place] = value;
}
t getArray(int place)
{
return myArray[place];
}
private:
int size;
t *myArray;
};
template<typename t>
Array<t>::Array(int s=10)
{
setSize(s);
myArray = new t[getSize()];
}
template<>
class Array<float>
{
public:
Array();
};
template<>
Array<float>::Array()
{
cout<<"Error";
}
#endif
Thanks
The implementation of the specialization's constructor isn't a template! That is, you just want to write:
Array<float>::Array()
{
std::cout << "Error";
}
Actually, it seems that you want to restrict the use of your 'Array' class template to not be used with 'float' in which case you might want to only declare but not define you specialization to turn the run-time error into a compile-time error:
template <> class Array<float>;
Of course, there are many variations how you can prevent instantiation of classes. Creating a run-time error seems to be the worst option, however.
Related
I have a template class which takes on roughly the form of the given code below.
template <int index = 0>
struct Thing {
void Hello();
void Greet(const char *name);
};
Which works just fine for its purpose, until one decides to try and call methods on itself. Say that you define the methods as shown below.
template <>
void Thing<>::Greet(const char *name) {
Hello();
printf(", %s!\n", name);
}
template <>
void Thing<>::Hello() {
printf("Hello");
}
Then calling Greet() yields an explicit specialisation error, which I find weird. The compiler ought to know all of the methods of this by its interface declaration, but for some reason it cannot resolve it in this case. This can be solved in one of two ways; either you must forward-declare any methods called on yourself, or make sure the methods are defined in an order that ensures that the ones you call are defined beforehand.
This issue is really annoying, because I have provided an interface declaration, and any specialisation of the template ought to conform to that same interface, so I really don't see why the compiler complains about this — is there any way to fix the issue without polluting the code with forward-declarations of each method, or having to order methods in a particular manner?
I hope you have some great ideas for solving the issue in a better way. Thank you in advance!
For ease of reproducing the issue, here's a snippet that will call the offending method.
int main(int argc, const char *argv[]) {
Thing<0> thing_with_zero;
thing_with_zero.Greet("World");
return 0;
}
You might specialize the whole class to ensure that specialization are seen:
// Primary template
// generic one
template <int index = 0>
struct Thing {
void Hello() {/*..*/}
void Greet(const char *name) {/*..*/}
};
// Specialization for index == 0
template <>
struct Thing<0> {
void Greet(const char *name) {
Hello();
printf(", %s!\n", name);
}
void Hello() {
printf("Hello");
}
};
Alternatively, you might drop specialization with the help of if constexpr (C++17):
template <int index = 0>
struct Thing
{
void Greet(const char *name) {
if constexpr (index == 0) {
Hello();
printf(", %s!\n", name);
} else {
// ...
}
}
void Hello() {
if constexpr (index == 0) {
printf("Hello");
} else {
// ...
}
}
};
In my application I use a class to flag elements that are inidicated by positive numbers (see code below). The template parameter of class Stamp is usually an unsigned integer. The advantage of flagging with a counter is, that clear() usually executes fast on huge vectors, as one increment of the counter invalidates all flags. Currently, only in my unit tests, I use boolean as template argument. Using boolean comes closest to the naive implementation of flagging numbers. But the increment operator for boolean is deprecated and will soon vanish from the standard and the compiler complains already about deprecation (not knowing that the part it's complaining about wouldn't even be executed in case of boolean). How would you specialize method clear() for the boolean case? I could not get it right, I tried it by just adding the the following definition.
template<>
void Stamp<bool>::clear() {
std::fill(stamped.begin(), stamped.end(), false);
}
Now the compiler complains about multiple definitions of clear(). How is template specialization done right in that case. And what other possibilities do I have to fix this class in modern c++?
template <class T> class Stamp {
private:
std::vector<T> stamped;
T stamp;
public:
Stamp(unsigned int size) {
stamped.resize(size, std::numeric_limits<T>::min());
stamp = std::numeric_limits<T>::min();
}
~Stamp() { }
void clear() {
if (stamp < std::numeric_limits<T>::max()) {
stamp++;
}
else {
std::fill(stamped.begin(), stamped.end(), std::numeric_limits<T>::min());
stamp = std::numeric_limits<T>::min() + 1;
}
}
void unset(unsigned int index) {
assert(index < stamped.size());
stamped[index] = std::numeric_limits<T>::min();
}
void set(unsigned int index) {
assert(index < stamped.size());
stamped[index] = stamp;
}
bool isStamped(unsigned int index) const {
return stamped[index] == stamp;
}
};
EDIT:
Using the answer of #Constructor I could come up with a method specialization by adding another definition of clear() to the header like this:
template<>
inline void Stamp<bool>::clear() {
std::fill(stamped.begin(), stamped.end(), false);
stamp = true;
}
This is kind of ugly but it actually works. Neither compiler nor tests choke on it.
The full (or explicit) function template specialization is not a template. So you should treat it like a normal function.
There are two possibilities not to violate ODR (One Definition Rule) when you are working with functions or methods of classes:
1) place the declaration of the function/method in a header file and its definition in some cpp file:
// Stamp.h
template<>
void Stamp<bool>::clear();
// Stamp.cpp
template<>
void Stamp<bool>::clear()
{
std::fill(stamped.begin(), stamped.end(), false);
stamp = true;
}
2) mark it as inline and place its definition in your header file:
// Stamp.h
template<>
inline void Stamp<bool>::clear()
{
std::fill(stamped.begin(), stamped.end(), false);
stamp = true;
}
Unfortunately, you can't specialize member functions without specializing the whole class. It is a silly language limitation that exists for historical reasons that don't (in my opinion) apply any longer.
Instead of specializing the whole class, you can make Stamp<T> inherit from StampBase<T> which you then specialize.
template <typename T> class StampBase;
template <typename T> class Stamp : public StampBase<T> {
// Code goes here!
void clear() {
StampBase<T>::clear_impl();
// Rest of code.
}
};
template <typename T> class StampBase {
protected:
void clear_impl() { /* T is NOT a bool */ }
};
template <> class StampBase<bool> {
protected:
void clear_impl() { /* T IS a bool */ }
};
This is more of a question of how the C++ compiler handles const typeid calls.
Hello! I am trying to make a tuple-style class, configured in such a way that I don't have to rewrite a bunch of the code with specializations.
So this is the general idea:
struct null_type{};
template <typename T1,typename T2=null_type,typename T3=null_type>
class ptestclass
{
private:
template<typename K1,typename K2,typename K3>
class barclass
{
public:
static inline void bar(std::tuple<K1,K2,K3>& vals,K1* otherval1,K2* otherval2,K3* otherval3)
{
Foo(tr1::get<0>(vals),*otherval1);
Foo(tr1::get<1>(vals),*otherval2);
Foo(tr1::get<2>(vals),*otherval3);
}
};
template<typename K1,typename K2>
class barclass<K1,K2,null_type>
{
public:
static inline void bar(std::tuple<K1,K2,null_type>& vals,K1* otherval1,K2* otherval2,null_type* otherval3)
{
Foo(tr1::get<0>(vals),*otherval1);
Foo(tr1::get<1>(vals),*otherval2);
}
};
template<typename K1>
class barclass<K1,null_type,null_type>
{
public:
static inline void bar(std::tuple<K1,null_type,null_type>& vals,K1* otherval1,null_type* otherval2,null_type* otherval3)
{
Foo(tr1::get<0>(vals),*otherval1);
}
};
/*
*Old Bar function...much more readable than bar class, but you cannot partially specialize
*member functions of a class
*
void inline bar(std::tuple<T1,T2,T3> otherval)
{
if (typeid(T1) != typeid(null_type))//constant check hopfully optomized out
{
Foo(vals.get(1),otherval.get(1));
}
if (typeid(T2) != typeid(null_type))//constant check hopfully optomized out
{
Foo(vals.get(2),otherval.get(2));
}
if(typeid(T3) != typeid(null_type))//constant check hopfully optomized out
{
Foo(vals.get(3),otherval.get(3));
}
}
*/
std::tuple<T1,T2,T3> vals;
template<typename K>
void static inline Foo(K& val,K& otherval)
{
//inlineable, short function that is called many (millions) of times per iteration
val += otherval;
}
template<>
void inline Foo<null_type>(null_type& val,null_type& otherval)
{
//inlineable, short function that is called many (millions) of times per iteration
throw "Foo called on null type";
}
public:
ptestclass()
{
printf("made object");
}
void one_iteration(T1* otherval1,T2* otherval2,T3* otherval3,size_t count)
{
for (int i = 0; i < count; ++i)
{
barclass<T1,T2,T3>::bar(vals,otherval1+i,otherval2+i,otherval3+i);
}
}
};
//exposed public class with specialized one_iteration interfaces
template <typename T1,typename T2=null_type,typename T3=null_type>
class testclass : public ptestclass<T1,T2,T3>
{
public:
void one_iteration(T1* otherval1,T1* otherval2,T1* otherval3,size_t count)
{
ptestclass::one_iteration(otherval1,otherval2,otherval3,count);
}
};
template <typename T1>
class testclass<T1,null_type,null_type> : public ptestclass<T1,null_type,null_type>
{
public:
void one_iteration(T1* otherval1,size_t count)
{
ptestclass::one_iteration(otherval1,NULL,NULL,count);
}
};
So my question is is this optimization even possible within C++? If not, it will probably make more sense for me to use an inheritance model on the child nodes rather then a template at this level. However, I am trying to avoid the continual check of the number of types specified and the cost of indirection.
I'm going to start diving into the assembly to see if that is what the compiler does...Just in case this is not standardized behavior, I'm using the Microsoft Visual C++ Compiler 10.0.
I think I misunderstood your question when I put my earlier comment.
Assuming you can use c++11, or you can use boost, you could use something like !std::is_same< T1, null_type >::value /*or boost::is_same...*/ instead of typeid(T1) != typeid(null_type). This uses TMP to resolve to a compile-time constant, which most compilers would have no trouble optimizing away.
This is more of a question of how the C++ compiler handles const typeid calls.
I didn't answer this specific question, but if I understand what you were actually looking for, the above should suffice.
Consider the following piece of code:
#include <cstddef>
template<size_t value> class dummy { };
class my_class
{
int m_member;
// Overload 1
template<size_t value>
friend void friend_func(dummy<value>*);
// Overload 2
template<size_t value>
friend void friend_func(int(*)[value]);
};
// Overload 1
template<size_t value>
void friend_func(dummy<value>*)
{
my_class instance;
instance.m_member = value;
}
// Overload 2
template<size_t value>
void friend_func(int(*)[value])
{
my_class instance;
instance.m_member = value;
}
int main(int argc, char* argv[])
{
dummy<5> d;
friend_func(&d); // call Overload 1
int arr[5];
friend_func(&arr); // call Overload 2 - error in MSVC!
return 0;
}
As you can see, the only difference between these two functions is that the second one takes a pointer to value ints instead of dummy<value>.
This code compiles just fine in GCC ($ gcc-4.7.2 test.cpp) and Clang (thanks WhozCraig), but throws the following error in MSVC (I tested 2012):
1>d:\path\to.cpp(32): error C2248: 'my_class::m_member' : cannot access private member declared in class 'my_class'
1> d:\path\to.cpp(8) : see declaration of 'my_class::m_member'
1> d:\path\to.cpp(7) : see declaration of 'my_class'
1> d:\path\to.cpp(40) : see reference to function template instantiation 'void friend_func<5>(int (*)[5])' being compiled
To me this looks like a bug. However, is there anyone who encountered such a behavior before? Is it really a bug, or maybe there's a particular reason for the error? Any quick workaround for this?
Edit: I've been able to find a proper workaround, see answer below.
It's definitely a bug: A template function parametrized on the size of an array cannot be declared as a friend of a class. It occurs when value is deduced as the size of the array for your friend template function. Here is a shortened version of your code that compiles fine. This example is the exact same code as your example except I specified the size of the array.
class my_class
{
int m_member;
template<size_t value>
friend void friend_func(int(*)[5]);
};
template<size_t value>
void friend_func(int(*)[5])
{
my_class instance;
instance.m_member = value;
}
int main()
{
int arr[5];
friend_func<5>(&arr);
}
One workaround it to pass the value as a second function argument:
template <typename T>
void friend_func(T, int value)
{
my_class instance;
instance.m_member = value;
}
Pretty sure it's a known issue with MSVS. Your specific issue is listed in the Portability Hints: Micrsoft Visual C++ on boost.org.
Look for Templates as Friends. I do not know the work around. However, I think you can make a class a friend. You may be able to use that as a work around.
I've figured a workaround that preserves the functionality yet does its job of preventing the error message. The idea is to use a proxy function and a proxy class to carry the pointer to the array and it's size. Here's the solution:
#include <cstddef>
// Workaround class for a bug in MSVC.
// https://connect.microsoft.com/VisualStudio/feedback/details/717749
// http://stackoverflow.com/questions/15149607
template<class element_type, size_t count>
class friend_declaration_bug_workaround
{
public:
typedef element_type(*ptr_type)[count];
private:
ptr_type m_arr;
public:
explicit friend_declaration_bug_workaround(ptr_type arr)
: m_arr(arr)
{
}
ptr_type value() const
{
return m_arr;
}
};
class my_class
{
int m_member;
friend void friend_func(int*);
template<size_t value>
friend void friend_func_workaround(friend_declaration_bug_workaround<int, value>);
};
template<size_t value>
void friend_func_workaround(friend_declaration_bug_workaround<int, value> workaround)
{
my_class instance;
instance.m_member = (*workaround.value())[0];
}
void friend_func(int* arr)
{
my_class instance;
instance.m_member = *arr;
}
template<size_t value>
void friend_func(int(*arr)[value])
{
friend_declaration_bug_workaround<int, value> workaround(arr);
return friend_func_workaround(workaround);
}
int main(int argc, char* argv[])
{
int value;
friend_func(&value); // call non-templated function
int arr[5];
friend_func(&arr); // call workarounded function
return 0;
}
Here's the deal. I've looked on this forum and I didn't find the information I'm searching for or I'm probably not able to repeat it for my problem. I have a class Table which is generic and I have a class named MyString.
template <typename typeGen, int DIM>
class Table {
public:
TableauGenerique() : index_(0) { //On initialise courant à 0
}
void add(typeGen type);
private:
typeGen tableGen_[DIM];
int index_;
};
My problem is with the add function.
I sometimes have to do this in the main.cpp: (which works well)
Table <float,6> tabFloat;
tabFloat.add(1.6564);
and at one point, I need to do this which doesn't work because I need to specialize the add function to create an object of MyString, to pass it the string and then store the object in the array (tableGen) :
TableauGenerique <MyString,4> tabString;
So I tried this (after the class), without success.
template <typename typeGen, int DIM>
void Table<typeGen,DIM>::add(typeGen type){ //Which is the generic one for float or ints
if(index_ < DIM) {
tableGen_[courant_] = type;
index_++;
}
}
template <class typeGen, int DIM>
void Table<typeGen,DIM>::add<string>(typeGen type) { //(line 75) Which is the specific or specialized function for myString
MyString str(type);
if(index_ < DIM) {
tableGen_[courant_] = str;
index_++;
}
}
So, How can I make this work because it doesn't compile at all, saying: line75 : error: expected initializer before '<' token and in the main it says not matching function to call Table::add(const char[6]),
I hope everything is clear enough. Let me know if somethings is unclear.
Thank you very much for your help !
template <class typeGen, int DIM>
void Table<typeGen,DIM>::add<string>(typeGen type)
You're trying to specialize add() when in fact it is not a function template to begin with. How do you expect it to work?
You probably meant: (specialization of the class)
template <int DIM>
void Table<string,DIM>::add(string type)
But then this is allowed only if you specialize the class itself. Without specializing the class, the above code would give compilation error!
EDIT:
You can read these online tutorials:
Introduction to C++ Templates
14.5 — Class template specialization
Template Specialization and Partial Template Specialization
Explicit specialization (C++ only)
If you can control the code of the MyString class, you can provide constructors that act as implicit conversions from float to MyString. An example:
#include <string>
#include <sstream>
#include <iostream>
class MyString {
public:
MyString(float number) {
std::stringstream buffer;
buffer << number;
value = buffer.str();
}
void print() {
std::cout << value << std::endl;
}
private:
std::string value;
};
template <class T>
class Foo {
public:
void DoStuff(T item) {
item.print();
}
};
int main() {
Foo<MyString> foo;
foo.DoStuff(1.342); // implicitly converts float to MyString
return 0;
}
This way, you do not need any specialization of the add method. However, implicit conversions are tricky, and you have be careful not to invoke them accidentally, and they may create ambiguities.
EDIT: Upon a second thought, my suggestion below is basically equivalent to
Table<MyString,4> tabString;
tabString.add(MyString("whatever"));
and therefore excessive and/or does not solve the problem. Feel free to ignore :)
I would extend the class Table with a generic method to add something from which you can construct an object of the desired type:
template <typename typeGen, int DIM>
class Table {
public:
Table() : index_(0) {}
void add(typeGen type);
// The additional method
template<typename T> void add(const T& src);
private:
typeGen tableGen_[DIM];
int index_;
};
template<typename typeGen, int DIM>
template<typename T>
void Table<typeGen,DIM>::add(const T& src) {
if(index_ < DIM) {
tableGen_[courant_] = typeGen(src);
index_++;
}
}
Note construction of a temporary typeGen object before the assignment.
Assuming that MyString object can be constructed from a string literal, i.e. from const char*, you can then use it as following:
Table<MyString,4> tabString;
tabString.add("whatever");
or if the above assumption is wrong, the following should probably work (because you constructed a MyString instance from a string instance):
tabString.add(string("whatever"));