Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template specialization for pointer?

Tags:

c++

templates

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

(1) Here's 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 use ubuntu16.04 x64, g++ 5.3, the 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;
}

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 book about pointer specialization is wrong ? Or I mis understand the meaning of this part in the book ? Or something else ?

Update about pointer specialization in 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 is the 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 means pointer specialization is needless ? Or maybe this feature behave differently on different compiler ?

like image 437
linrongbin Avatar asked Jan 19 '17 09:01

linrongbin


People also ask

Can template type be a pointer?

A template has only one type, but a specialization is needed for pointer, reference, pointer to member, or function pointer types. The specialization itself is still a template on the type pointed to or referenced.

What is template specialization used for?

This is called template specialization. Template allows us to define generic classes and generic functions and thus provide support for generic programming. Generic programming is an approach where generic data types are used as parameters in algorithms so that they work for variety of suitable data types.

What is the difference between generic class template and specialization template?

Key differences between generics and C++ templates: Generics are generic until the types are substituted for them at runtime. Templates are specialized at compile time so they are not still parameterized types at runtime. The common language runtime specifically supports generics in MSIL.

How many types of templates are there in C?

Correct Option: C There are two types of templates. They are function template and class template.


2 Answers

as you've been already told, partial specialization of function templates are 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 simpler syntax, wait for concepts

like image 96
Andrei R. Avatar answered Oct 12 '22 20:10

Andrei R.


The error message told you what is wrong:

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

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

like image 35
eerorika Avatar answered Oct 12 '22 19:10

eerorika