C ++ template specialization for pointer?

I read the book <C ++ Templates - A Complete Guide> and learned the specialization of the template for a pointer. (maybe I misunderstand this part of the book)

(1) Here is my simple template:

#include <iostream> template<typename T> void Function(const T& a) { std::cout << "Function<T>: " << a << std::endl; } template<typename T> void Function<T*>(const T* a) { std::cout << "Function<T*>: " << a << std::endl; } int main(void) { Function(1); Function(1.2); Function("hello"); Function((void*)0x25); return 0; } 

I am using ubuntu16.04 x64, g ++ 5.3, compiler report:

 $ g++ main.cpp -o main.exe main.cpp:10:29: error: non-type partial specialization 'Function<T*>' is not allowed void Function<T*>(const T* a) 

(2), but this code is correct:

 #include <iostream> template<typename T> void Function(const T& a) { std::cout << "Function<T>: " << a << std::endl; } int main(void) { Function(1); Function(1.2); Function("hello"); Function((void*)0x25); return 0; } 

The result shows:

 $ g++ main.cpp -o main.exe $ ./main.exe Function<T>: 1 Function<T>: 1.2 Function<T>: hello Function<T>: 0x25 

My question is: is the pointer specialization book wrong? Or am I misunderstanding the meaning of this part in the book? Or something else?

Updating pointer specialization in a class.

(3) template class with pointer specialization:

 #include <iostream> template<typename T> struct Base { T member; Base(const T& a) : member(a) { } void hello() { std::cout << member << std::endl; } }; template<typename T> struct Base<T*> { T* member; Base(T* a) : member(a) { } void hello() { std::cout << member << std::endl; } }; int main(void) { Base<int> b1(12); Base<double> b2(2.4); Base<char*> b3("hello"); Base<void*> b4((void*)0x25); b1.hello(); b2.hello(); b3.hello(); b4.hello(); return 0; } 

this code is correct with one warning:

 $ g++ main.cpp -o main.exe main.cpp: In function 'int main()': main.cpp:37:27: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] Base<char*> b3("hello"); ^ $ ./main.exe 12 2.4 hello 0x25 

(4) template class without pointer specialization:

 #include <iostream> template<typename T> struct Base { T member; Base(const T& a) : member(a) { } void hello() { std::cout << member << std::endl; } }; int main(void) { Base<int> b1(12); Base<double> b2(2.4); Base<char*> b3("hello"); Base<void*> b4((void*)0x25); b1.hello(); b2.hello(); b3.hello(); b4.hello(); return 0; } 
Result

same:

 $ g++ main.cpp -o main.exe main.cpp: In function 'int main()': main.cpp:39:27: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] Base<char*> b3("hello"); ^ $ ./main.exe 12 2.4 hello 0x25 

Does this mean that pointer specialization is useless? Or maybe this function works differently on different compilers?

+5
source share
3 answers

The error message told you what was wrong:

 non-type partial specialization 'Function<T*>' is not allowed 

You can only partially specialize types (classes). You tried to partially specialize a function. Functions are not types; You can fully specialize them.

+3
source

As you said, partial specialization of function templates is not allowed. You can use std::enable_if for this:

 template <typename T, typename std::enable_if_t<!std::is_pointer<T>::value>* = 0> void func(T val) { std::cout << val << std::endl; } template <typename T, typename std::enable_if_t<std::is_pointer<T>::value>* = 0> void func(T val) { func(*val); } 

If you are looking for a simpler syntax, wait for the concepts

+4
source

Two problems:

  • You are not allowed to partially specialize the function.

  • The behavior (void*)0x25 is undefined. With the exception of nullptr , you are not allowed to point to a memory pointer that you do not have, with the exception of the last one element of the array and the one after the scalar address.

+1
source

Source: https://habr.com/ru/post/1263044/


All Articles