I'm trying to make a function accept different arguments depending on the enum.
// cake.h
#pragma once
#include <utility>
enum class TYPE { CupCake, Jelly, BirthdayCake };
struct cake_tin { /* etc etc */ };
/** Fills in different ingredients for different types of cake */
template <TYPE, typename ...Args>
void fill_tin(cake_tin &tin, Args... args);
/** Bakes a cake */
template <TYPE type, typename ...Args>
void bake_cake(Args&&...args) {
cake_tin tin;
fill_tin<type>(tin, std::forward<Args>(args)...);
}
.cpp file contains the specialisations of the function
// cake.cpp
#include "cake.h"
// If I put this in cake.h, I get multiple definition error (since the template's fully specalised), but if I move this to the .cpp file, I get undefined reference when I compile
template <>
void fill_tin<TYPE::CupCake>(cake_tin &tin, int cherries) {
// ... etc etc
}
template <>
void fill_tin<TYPE::Jelly>(cake_tin &tin, bool wobble) {
// ... etc etc
}
For completeness
// main.cpp
#include "cake.h"
int main() {
bake_cake<TYPE::CupCake>(1);
}
Another file that includes cake.h
// other.cpp
#include "cake.h"
Compile with clang++ -Wall -Wextra -std=c++11 main.cpp other.cpp -o main
I've tried putting in declarations
template <> void fill_tin<TYPE::CupCake>(cake_tin &tin, int cherries);
template <> void fill_tin<TYPE::Jelly>(cake_tin &tin, bool wobble);
and still can't get that template instantiated. If I move the specialisations into the header then they'll cause redefinition when the header is included in multiple compilation units at the link stage.
My question is: How can I get this to work, or is there a better way of doing this?