Search code examples
c++c++17unordered-mapstd-pair

Interpreting unresolved externals C++


I'm having a go at making a minecraft renderer. When loading the world from the region files, it stores the parsed NBT data in an unordered map, with the nbt data as the value and the global chunk coordinates as the key. Specifically unordered_map<pair<int, int>, CompoundTag*> (the compound tag being the NBT data)

However, I'm running into a compile time error that seems to point at the unordered map. It is as follows.

Error LNK2001 unresolved external symbol "class std::unordered_map,struct Chunk,struct std::hash >,struct std::equal_to >,class std::allocator const ,struct Chunk> > > __cdecl createChunks(class std::unordered_map,class CompoundTag,struct std::hash >,struct std::equal_to >,class std::allocator const ,class CompoundTag> > > &,class Asset &)" (?createChunks@@YA?AV?$unordered_map@U?$pair@HH@std@@UChunk@@U?$hash@U?$pair@HH@std@@@2@U?$equal_to@U?$pair@HH@std@@@2@V?$allocator@U?$pair@$$CBU?$pair@HH@std@@UChunk@@@std@@@2@@std@@AEAV?$unordered_map@U?$pair@HH@std@@VCompoundTag@@U?$hash@U?$pair@HH@std@@@2@U?$equal_to@U?$pair@HH@std@@@2@V?$allocator@U?$pair@$$CBU?$pair@HH@std@@VCompoundTag@@@std@@@2@@2@AEAVAsset@@@Z)

I've solved unresolved externals before, and usually it's because I forgot to include an external file (hence the name) that the program needs. However, this time I'm fairly certain I have everything it needs. I've included unordered_map at the top of the of the file. I've included the header where Chunk is defined, and I'm aware of the need for the custom build hash and equal_to functions, and provided them with the following in a header file that is included.

namespace std
{
    template<>
    struct hash<pair<int32_t, int32_t>>
    {
        size_t operator ()(const pair<int32_t, int32_t>& value) const
        {
            uint64_t key = ((uint64_t)value.first) << 32 | (uint64_t)value.second;
            key ^= (key >> 33);
            key *= 0xff51afd7ed558ccd;
            key ^= (key >> 33);
            key *= 0xc4ceb9fe1a85ec53;
            key ^= (key >> 33);
            return (size_t)key;
        }
    };


    template<>
    struct equal_to<pair<int32_t, int32_t>>
    {
        bool operator ()(const pair<int32_t, int32_t>& v1, const pair<int32_t, int32_t>& v2) const
        {
            return (v1.first == v2.first) && (v1.second == v2.second);
        }
    };
}

The only other thing I thought I might need to do is provide a custom allocator? But everything I found about using pairs as keys in unordered_maps says that it's not necessary. I'm a little stumped, and would be grateful for any insight. If you have any questions or want to see more of the code please ask. It's on my github if you want to look at the project as a whole, but if you (justifiably) don't want to sort through that whole mess please just ask for clarification on anything or extra information.

Edit 1, I parsed the error the best I can.

class std::unordered_map
<
    struct std::pair
    <
        int,
        int
    >,
    struct Chunk *,
    struct std::hash
    <
        struct std::pair
        <
            int,
            int
        > 
    >,
    struct std::equal_to
    <
        struct std::pair
        <
            int,
            int
        >
    >,
    class std::allocator
    <
        struct std::pair
        <
            struct std::pair
            <
                int,int
            > const,
            struct Chunk *
        > 
    > 
>

__cdecl createChunks(
    class std::unordered_map
    <
        struct std::pair
        <
            int,
            int
        >,
        class CompoundTag *,
        struct std::hash
        <
            struct std::pair
            <
                int,
                int
            >
        >,
        struct std::equal_to
        <
            struct std::pair
            <
                int,
                int
            >
        >,
        class std::allocator
        <
            struct std::pair
            <
                struct std::pair
                <
                    int,
                    int
                > const,
                class CompoundTag *
            > 
        > 
    >&
    ,class Asset&
) 


(?createChunks@@YA?AV?$unordered_map@U?$pair@HH@std@@PEAUChunk@@U?$hash@U?$pair@HH@std@@@2@U?$equal_to@U?$pair@HH@std@@@2@V?$allocator@U?$pair@$$CBU?$pair@HH@std@@PEAUChunk@@@std@@@2@@std@@AEAV?$unordered_map@U?$pair@HH@std@@PEAVCompoundTag@@U?$hash@U?$pair@HH@std@@@2@U?$equal_to@U?$pair@HH@std@@@2@V?$allocator@U?$pair@$$CBU?$pair@HH@std@@PEAVCompoundTag@@@std@@@2@@2@AEAVAsset@@@Z)    MCRenderer  C:\Users\noahm\source\repos\noahwhygodwhy\MCRenderer\MCRenderer\MCRenderer.obj  1   

Solution

  • The error message is long, but if you read it carefully it's referring to a missing function called createChunks.

    The unordered_map is simply the return type (and parameter type) of that function.

    BTW you seem to have a misunderstanding, undefined references are not generally caused by missing header files, a missing header file would cause a compilation error. Unresolved externals are generally caused by missing files (object files or library files) in the linking step.

    UPDATE

    Having looked at your code I can see that the problem is a typo. In chunkPipeline.hpp you declare a function createChunks but in chunkPipeline.cpp the same function is called createChunk. Disproving my earlier assertion that undefined references are caused missing files during linking, they can also be caused by typos.