C++ templates behaving as if they're not there?

Discussion in 'Computer Programming, Emulation, and Game Modding' started by StackMasher, Apr 18, 2017.

  1. StackMasher
    OP

    StackMasher GBAtemp Regular

    Member
    106
    51
    Nov 29, 2016
    So here's my code:
    Code:
    //cartridge.h
    #ifndef CARTRIDGE_INCLUDED
    #define CARTRIDGE_INCLUDED
    
    #include <cstdint>
    #include <cstddef>
    #include "type.h"
    #include "../types.h"
    #include "mbc.h"
    #include "../util/smartArray.h"
    
    namespace Gameboy {
        class Cartridge {
            public:
                constexpr static Address header = 0x100;
                constexpr static unsigned int romBankSize = 0x4000;
                constexpr static unsigned int ramBankSize = 0x2000;
    
            protected:
                Util::SmartArray<Byte*> romBanks;
                Util::SmartArray<Byte*> ramBanks;
    
                unsigned int romBank0 = 0;
                unsigned int romBank1 = 1;
                unsigned int ramBank = 0;
    
                int romSize = 0;
                int ramSize = 0;
    
                MBC mbc;
                const char* name = NULL;
                bool nameCopied = false;
                CartType type;
    
            public:
                void clear();
                void load(const char* romname);
                void update();
    
                template <typename type> type read(Address address);
                template <typename type> void write(Address address, type toWrite);
                const char* getName();
    
                Cartridge(const char* romname = NULL);
                ~Cartridge();
        };
    }
    
    #include "cartridgeIO.h"
    
    #endif
    
    //cartridgeIO.h
    template <typename type> type Gameboy::Cartridge::read(Address address) {
        if (address <= 0x3FFF) {
            return *((type*)romBanks[romBank0][address]);
        }
        else if (address <= 0x7FFF) {
            return *((type*)romBanks[romBank1][address-0x3FFF]);
        }
        else if (address >= 0xA000 && address <= 0xBFFF && mbc.getType()!=2) {
            return *((type*)ramBanks[ramBank][address-0x9FFF]);
        }
        else {
            return mbc.read<type>(address);
        }
    }
    
    template <typename type> void Gameboy::Cartridge::write(Address address, type toWrite) {
        if (address >= 0xA000 && address <= 0xBFFF && mbc.getType()!=2) {
            *((type*)&ramBanks[ramBank][address-0x9FFF]) = toWrite;
        }
        else {
            mbc.write<type>(address, toWrite);
        }
    }
    And here's the errors the compiler produces:
    Code:
    g++-6 -g -c gb.cpp -o .build/gb.o
    In file included from cartridge/cartridge.h:48:0,
                     from gb.h:6,
                     from gb.cpp:1:
    cartridge/cartridgeIO.h: In member function ‘type Gameboy::Cartridge::read(Gameboy::Address)’:
    cartridge/cartridgeIO.h:12:29: error: expected primary-expression before ‘>’ token
             return mbc.read<type>(address);
                                 ^
    cartridge/cartridgeIO.h: At global scope:
    cartridge/cartridgeIO.h:16:74: error: ‘type’ is not a type
     template <typename type> void Gameboy::Cartridge::write(Address address, type toWrite) {
                                                                              ^~~~
    cartridge/cartridgeIO.h:16:31: error: prototype for ‘void Gameboy::Cartridge::write(Gameboy::Address, int)’ does not match any in class ‘Gameboy::Cartridge’
     template <typename type> void Gameboy::Cartridge::write(Address address, type toWrite) {
                                   ^~~~~~~
    In file included from gb.h:6:0,
                     from gb.cpp:1:
    cartridge/cartridge.h:40:43: error: candidate is: template<class type> void Gameboy::Cartridge::write(Gameboy::Address, type)
                 template <typename type> void write(Address address, type toWrite);
                                               ^~~~~
    
    So basically it acts as if the templates are not there before the definition, and I can't figure out why
     
  2. bailli

    bailli GBAtemp Regular

    Member
    185
    21
    Oct 16, 2006
    Gambia, The
    Hm not really sure...

    Do you know that header files need to contain the full template's code and not only the forward declaration?

    EDIT: Also: Maybe you are not referencing the correct namespace(s)?
     
    Last edited by bailli, Apr 18, 2017
  3. StackMasher
    OP

    StackMasher GBAtemp Regular

    Member
    106
    51
    Nov 29, 2016
    I include cartridgeIO.h at the bottom of cartridge.h
     
  4. bailli

    bailli GBAtemp Regular

    Member
    185
    21
    Oct 16, 2006
    Gambia, The
    The first error is about not finding mbc.read - did you check that this template is accessible?

    Also see my above edit. Did you check namespaces? There is an error "‘type’ is not a type" <- is it actually "GameBoy::type"?
    (Namespaces sometimes confuse me - also they are generally a good idea...)
     
  5. StackMasher
    OP

    StackMasher GBAtemp Regular

    Member
    106
    51
    Nov 29, 2016
    It's because I have a member variable called "type" in Gameboy::Cartridge aswell
    I also haven't implemented mbc.read<type> and mbc.write<type> yet
    Fixed now :)