80604

templates function specialization, c++

Question:

I am practicing function specialization, and I was trying to create a little storage object with a specialized print function. Here's my code:

#ifndef STORAGE_HPP_ #define STORAGE_HPP_ #include <iostream> using namespace std; template <typename T, int size> class Storage { //LINE 16 ERROR public: Storage():arr(new T*[size]){}; ~Storage() { for (int i = 0; i < size; i++) { delete arr[i]; } delete[] arr; } void push(T obj, int i) { arr[i] = new T(obj); } void print() { for (int i = 0; i < size; i++) { cout << *arr[i]; } cout << endl; } private: T** arr; }; template <typename T, int size> void Storage<int,size>::print() //LINE 38 ERROR { for (int i = 0; i < size; i++) { cout << (char) *arr[i]; } cout << endl; } #endif /* STORAGE_HPP_ */

And I get this error:

../Storage.hpp:38:63: error: invalid use of incomplete type class Storage<int, size> ../Storage.hpp:9:1: error: declaration of ‘class Storage<int, size>’

So, first question: can specialized functions be implemented inside a class? I tried but got an error. Second, why do I get the error I've attached? Thanks!

EDIT: I tried something new as someone here suggested. I've change print inside the class to be only void print() and I've implemented it outside so I can overload the function. Here:

template <typename T, int size> void Storage<T,size>::print() { for (int i = 0; i < size; i++) { cout << *arr[i]; } cout << endl; } template <typename T, int size> void Storage<int,size>::print() //ERROR HERE { for (int i = 0; i < size; i++) { cout << *arr[i]; } cout << endl; }

Now I get invalid use of incomplete type ‘class Storage<int, size>’Where I wrote ERROR HERE (obviously!) I understand that's a common solution, am I right? And why do I get this error?

Answer1:

The problem is that you are trying to use a partial specialization of the entire <em>class</em> without having <em>defined</em> the partially-specialized class.

If print were itself a function template, the situation would be different, because you can indeed specialize function templates. However, your construction only has the entire class as a template.

This means that template <typename T, int n> class Storage<T, n> and template <int n> class Storage<int, n> are entirely different, unrelated classes. Thus you must first <em>define</em> the latter class:

template<int n> class Storage<int, n> { // define everything }; template<int n> void Storage<int, n>::print() { /* implement */ }

Consider that the partial specialization Storage<int, n> may be an entirely different class from the primary template, and it may have totally different member functions. The compiler has no way of knowing this until you actually define that class.

<hr />

Following sbi's comment, here's one idea:

//... in the class definition template<typename S, int m> friend void print_helper(const Storage<S, m> &); template<int m> friend void print_helper(const Storage<int, m> &); void print() { print_helper(*this); }

// outside: template <typename S, int size> void print_helper(const Storage<S, size> & s) { // ... } template <int size> void print_helper(const Storage<int, size> & s) { // ... }

Instead of the friend you could also make the helper function template static, but that might add a lot of code bloat, since you'll have two static function templates per class type, rather than just two globally.

Answer2:

Partial specializations always need to use the complete template, since they define a template too.

So this would not work:

template <int size> void Storage<int,size>::print()

Full specializations of member functions can be done out of line for single member functions, because they define functions.

So this would work:

template <> void Storage<int,44>::print()

And you can not declare/define any (partial) specializations within the primary template.

Answer3:

I don't think you can use partial specialisation on a single method. You can only use full specialisation.

The question is: why do you want to use an array with a specified size? Why not just use an std::vector and let the push() function size it dynamically (with std::vector::push_back() )?

Answer4:

The only error I can see is an extraneous typename T in your specialization. It should be:

template <int size> void Storage<int,size>::print() {...}

Recommend

  • How to compare results between C++ and MATLAB?
  • CGAL: How to efficiently calculate the area of facets of a polyhedron?
  • C++ Boost ptr_map serialization error
  • Flot returns incorrect x value (mm/dd/yy - date) after zoom for stack bar chart
  • Iterating over a container bidirectionally
  • 'Enemy' was not declared in this scope?
  • std::system Exception when instantiating a singleton object
  • Runtime error in UVA Online Judge [closed]
  • OpenMP and File I/O
  • JSON - slashes not escaping
  • Inversing an interpolation of rotation
  • PayPal API Listener Website Payments Standard URI
  • redirect_to root_url and return unless @user.activated
  • How does this usort cmp function actually work?
  • How to determine if there are bytes available to be read from boost:asio:serial_port
  • why overloaded new operator is calling constructor even I am using malloc inside overloading functio
  • Adding a button at the bottom of a table view
  • Getting last autonumber in access
  • AES padding and writing the ciphertext to a disk file
  • Javascript + PHP Encryption with pidCrypt
  • Convert array of 8 bytes to signed long in C++
  • Build own AppleScript numerical error handling
  • Websockets service method fails during R startup
  • Google cloud sdk not working when python points python3
  • Delete MySQLi record without showing the id in the URL
  • GridView Sorting works once only
  • Is there a mandatory requirement to switch app.yaml?
  • Linker errors when using intrinsic function via function pointer
  • Hits per day in Google Big Query
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • Getting Messege Twice Using IMvxMessenger
  • LevelDB C iterator
  • Linking SubReports Without LinkChild/LinkMaster
  • unknown Exception android
  • EntityFramework adding new object to nested object collection
  • XCode 8, some methods disappeared ? ex: layoutAttributesClass() -> AnyClass
  • Checking variable from a different class in C#
  • How can i traverse a binary tree from right to left in java?
  • failed to connect to specific WiFi in android programmatically
  • How can I use threading to 'tick' a timer to be accessed by other threads?