Home > other >  C template specialization problem with const char*
C template specialization problem with const char*

Time:07-26

I have a template function void foo(const T&). I need specialized implementations for [T = int] and [T = const char*].

#include <iostream>

template<class T>
void foo(const T& arg)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    std::cout << arg << std::endl;
}

template<>
void foo(const int& arg)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    std::cout << arg << std::endl;
}

int main(int argc, char *argv[])
{
    int i = 42;
    const char *bar = "xyz";
    foo(i);
    foo(bar);
    return 0;
}

The specialization for [T = int] works, the output is:

void foo(const T&) [with T = int]
42
void foo(const T&) [with T = const char*]
xyz

But, it won't compile if I try to specialize for [T = const char*] like so:

template<>
void foo(const char*& arg)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    std::cout << arg << std::endl;
}

17:6: error: template-id 'foo<>' for 'void foo(const char*&)' does not match any template declaration

What has me puzzled is that it appears to correctly deduce [T = const char*] when no specialization is present, but complains if I try to implement one.

Any ideas where I'm going wrong?

CodePudding user response:

You need a second const

template<>
void foo(const char* const& arg)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    std::cout << arg << std::endl;
}

The template requires a const reference, but const char*& is a reference to a pointer to a const char.

template<class T>
void foo(const T& arg)

Even better would be to use overloads instead of function template specialization, e.g.

template<class T>
void foo(const T& arg)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    std::cout << arg << std::endl;
}

void foo(const int& arg)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    std::cout << arg << std::endl;
}


void foo(const char*& arg)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    std::cout << arg << std::endl;
}

CodePudding user response:

In this function template declaration

template<class T>
void foo(const T& arg)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    std::cout << arg << std::endl;
}

you have a constant reference to the type T. When the function is called like

const char *bar = "xyz";
foo(bar);

then the deduced type T is const char * (the type of a pointer to a string literal). You may imagine it the following way

typedef const char *T;

So the constant reference to the type T will look like

const char * const &

Here is a demonstration program.

#include <iostream>
#include <type_traits>

template<class T>
void foo(const T& arg)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    std::cout << arg << std::endl;
    std::cout << std::boolalpha
        << std::is_same_v<T, const char *> << '\n';
    std::cout << std::boolalpha
        << std::is_same_v<decltype( arg ), const char * const &> << '\n';
}

int main(int argc, char *argv[])
{
    const char *bar = "xyz";
    foo(bar);
    return 0;
}

The program output is

void foo(const T &) [T = const char *]
xyz
true
true
  • Related