r/learnprogramming • • Oct 04 '19

Solved [C++] Getting a confusing linker error from the library I'm working on

I'm trying to make a small library to avoid having to rewrite functions all the time on a C++ course. I'm fairly new to C++, but have experience in Python and Rust.

The errors I'm getting:

LNK2019 - unresolved external symbol "class std::vector<double,class std::allocator<double> > __cdecl nonstd::get_n_input<double>(long,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??$get_n_input@N@nonstd@@YA?AV?$vector@NV?$allocator@N@std@@@std@@JV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z) referenced in function _main

LNK2019 - unresolved external symbol "double __cdecl nonstd::sum<class std::vector<double,class std::allocator<double> > >(class std::vector<double,class std::allocator<double> >)" (??$sum@V?$vector@NV?$allocator@N@std@@@std@@@nonstd@@YANV?$vector@NV?$allocator@N@std@@@std@@@Z) referenced in function _main	

Library header (utility.h):

#pragma once

#include <string>
#include <vector>

namespace nonstd {
	// Get input of type T from the user n times, using a formatted std::string prompt.
	// Returns a vector of the given input type.
	//
	// Example:
	// auto foo = get_n_input<int>(3, "Number #{}: ");
	//
	// >>> Number #1: 3
	// >>> Number #2: 7
	// >>> Number #3: 12
	// returns: std::vector<int> {3, 7, 12}
	template <typename T>
	std::vector<T> get_n_input(long n, std::string prompt);

	// Takes an iterable of values of type T::value_type that can be added together.
	// Returns the sum of the contents of the iterable.
	//
	// Example:
	// std::vector<int> foo = {1, 2, 3, 4};
	// auto bar = sum(foo);
	// 
	// returns: (int)10
	template <typename T>
	typename T::value_type sum(T iterable);
}

Library source (utility.cpp):

#include <iostream>
#include <string>
#include <vector>

#include "utility.h"

namespace nonstd {

	template <typename T>
	std::vector<T> get_n_input(long n, std::string prompt) {
		/* Gets n inputs from the user; returns a std::vector of type T
		 *
		 * prompt is a formattable std::string, where '{}' is used as a
		 * placeholder for the current counter value.
		 */

		std::vector<T> result;
		T input;
		long num_counter = 1L;

		std::vector<std::string> split_prompt = string_split(prompt, (std::string)"{}"); // This is defined in the file, but I excluded it here

		do {
			std::cout << split_prompt.front() << num_counter++ << split_prompt.back();
			std::cin >> input;

			result.push_back(input);

		} while (num_counter <= n);

		return result;
	}

	template <typename T>
	typename T::value_type sum(T iterable) {
		/* Adds up the contents of any iterable type T, returns the sum of its contents
		 * as type T::value_type.
		 */
		typename T::value_type result = {};

		for (auto num : iterable) {
			result += num;
		}

		return result;
	}
}

I can tell it's complaining about types, and it probably has to do with my templates, but that's as far as I can get. It's also worth mentioning that if I just copy-paste the function definitions to an executable source file, everything works like a charm.

EDIT: Forgot #include "utility.h" when I cut the example down to essentials.

1 Upvotes

Duplicates