WedaPashi
WedaPashi

Reputation: 3872

Resolving compilation error with template specialization

I am having issues in understanding and fixing a compiler error that I see with MinGW (UCRT64) C++20, but that I don't see when I build the code with MSBuild C++11.

header.h: (Only relevant code)

#pragma once
// Has other necessary inclusions
#include <string>
#include <map>

struct Foo {
    // Assumptions:
    // Has some members
    // Has variants of constructors
};

using Fooes = std::multimap<size_t, Foo>;

template <typename S>
std::string retrieveData(S& params, const std::string& tag, const std::string& initval);

extern template bool retrieveData<const Fooes>(const Fooes& params, const std::string& tag, bool initval);

// There are similar such retrieveData `extern template`s which deals with different data types for args and returning
// I have commented them out with the thought that I'll fix one and deal with the remaining later

Source.cpp: (Only relevant code)

// Safe to assume that:
// Has other necessary inclusions
#include <header.h>

Fooes::const_iterator retrieveEntry(const Fooes& params, const std::string& tag) {
    // Impl that is already functional, has no warnings
    }

template<>
std::string retrieveData<const TaxParameters>(const TaxParameters& params, const std::string& tag, const std::string& initval) {
    const auto matchedEntry = retrieveEntry(params, tag);
    if (matchedEntry == params.cend()) {
        return initval;
    }
    return matchedEntry->second.value;
}

// There are similar such retrieveData impl which deals with different data types for args and returning
// I have commented them out with the thought that I'll fix one and deal with the remaining later

Compilation Error that I get:

error: specialization of 'std::string retrieveData(S&, const std::string&, const std::string&) [with S = const std::multimap<long long unsigned int, Foo>; std::string = std::__cxx11::basic_string<char>]' after instantiation
std::string retrieveData<const Fooes>(const Fooes& params, const std::string& tag, const std::string& initval) 

I looked at the CPP reference to understand the Explicit instantiations as I have never worked with those. It talks about usage of extern template in following way:

extern template return-type name < argument-list > ( parameter-list ) ; (3) (since C++11)
extern template return-type name ( parameter-list ) ;   (4) (since C++11)

And,

An explicit instantiation definition forces instantiation of the function or member function they refer to. It may appear in the program anywhere after the template definition, and for a given argument-list, is only allowed to appear once in the program, no diagnostic required.

An explicit instantiation declaration (an extern template) prevents implicit instantiations: the code that would otherwise cause an implicit instantiation has to use the explicit instantiation definition provided somewhere else in the program.

I am so confused to figure out in my code which one is explicit instantiation definition and which one is explicit instantiation declaration, And do I refer to the implementation of the function in source.cpp as Specialization as the compilation error says.

What is the correct way to fix this error?

Upvotes: 1

Views: 90

Answers (1)

Haiyu Zhu
Haiyu Zhu

Reputation: 21

in header.h, the return type of specialization should be

extern template std::string
retrieveData<const Fooes>(const Fooes& params, const std::string& tag, bool initval);

Upvotes: 2

Related Questions