1

I'm just learning C++ and and have run into a problem that the Sublime Text console debugger can't solve for me. I have a stringify function with two arguments, a const auto& arr, and a const std::string& ch. I'd like to be able to initialize this in my main.h file that I import in every single .cpp file for my project so it is available to the global scope.

I've tried the normal way of doing it, just defining it first in main.h and then filling out the rest within my main.cpp

main.cpp

std::string stringify(const auto& arr, const std::string& ch)
{
    std::stringstream ss;
    unsigned i = 0;
    for (auto& element : arr) {
        ++i;
        // add element to s
        ss << element;
        // if element isnt the last one.
        (i != arr.size()) ? ss << ch : ss;
    }
    return ss.str();
}

main.h

#ifndef MAIN_H
#define MAIN_H

#include <iostream>
#include <string>
#include <sstream>
#include <array>
#include <vector>
#include <iterator>
#include <algorithm>

std::string stringify(const auto& arr, const std::string& ch);

#endif // MAIN_H

I constantly get errors for "undefined reference to function" stringify no matter what I try unless I put the full function definition within main.h. What am I missing here? I've been reading through docs and can't seem to figure it out.

melpomene
  • 84,125
  • 8
  • 85
  • 148

2 Answers2

3

Note using auto in a function parameter, like your const auto& arr, is not currently Standard C++. It will be valid in C++20, but some compilers already implement it for other C++ versions as an extension.

What it actually does, though, is makes the function into a function template, since the actual type of the parameter now needs to be deduced from the function arguments. So the declaration

std::string stringify(const auto& arr, const std::string& ch);

is essentially equivalent to

template <typename T>
std::string stringify(const T& arr, const std::string& ch);

Because your function acts like a template, its definition needs to be in a header file so that the compiler can instantiate it as needed whenever it is used with a new type of arr. (See Why can templates only be implemented in the header file?)

aschepler
  • 70,891
  • 9
  • 107
  • 161
  • thanks! Guess I gotta wait until C++20. Is there another way I can do this to not have code in my .h file? – Nelson McCullough May 18 '19 at 16:34
  • C++20 will also require you to put the definition in a header file. Or like any template, you can have the implementation in a source file if you define some explicit instantiations, but this only helps if you know all the types that should ever be used with the function. – aschepler May 18 '19 at 17:19
1

When you define a parameter as auto the compiler will use templates in background:

Your function:

std::string stringify(const auto& arr, const std::string& ch);

is equals to:

template<class T>
std::string stringify(const T& arr, const std::string& ch);

And template functions need to be defined (not only declared). So, the option is to define it in the header file.

lucas.exe
  • 119
  • 3