Simplify the router

There's a lot of complexity left in the router.  The recent decision to
only support string arguments means that this can be significantly
cleaned up.

In some cases, this is done to simply expand the variadic template and
handle all parameter cases up to 5 (which should be the max we ever
see).  While this might seem like it's not very DRY friendly (Don't
repeat yourself) this is significantly better than what we had, which
was very tough to deciper.

Tested: Redfish service validator passes

Change-Id: Ic72e54cffd7b9f4a85e6c9d143c45fa20530a2cd
Signed-off-by: Ed Tanous <edtanous@google.com>
diff --git a/http/routing.hpp b/http/routing.hpp
index 97daef1..1b2c131 100644
--- a/http/routing.hpp
+++ b/http/routing.hpp
@@ -376,16 +376,60 @@
     }
 
     template <uint64_t N>
-    typename black_magic::Arguments<N>::type::template rebind<TaggedRule>&
-        newRuleTagged(const std::string& rule)
+    auto& newRuleTagged(const std::string& rule)
     {
-        using RuleT = typename black_magic::Arguments<N>::type::template rebind<
-            TaggedRule>;
-        std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
-        RuleT* ptr = ruleObject.get();
-        allRules.emplace_back(std::move(ruleObject));
-
-        return *ptr;
+        constexpr size_t numArgs = utility::numArgsFromTag(N);
+        if constexpr (numArgs == 0)
+        {
+            using RuleT = TaggedRule<>;
+            std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
+            RuleT* ptr = ruleObject.get();
+            allRules.emplace_back(std::move(ruleObject));
+            return *ptr;
+        }
+        else if constexpr (numArgs == 1)
+        {
+            using RuleT = TaggedRule<std::string>;
+            std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
+            RuleT* ptr = ruleObject.get();
+            allRules.emplace_back(std::move(ruleObject));
+            return *ptr;
+        }
+        else if constexpr (numArgs == 2)
+        {
+            using RuleT = TaggedRule<std::string, std::string>;
+            std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
+            RuleT* ptr = ruleObject.get();
+            allRules.emplace_back(std::move(ruleObject));
+            return *ptr;
+        }
+        else if constexpr (numArgs == 3)
+        {
+            using RuleT = TaggedRule<std::string, std::string, std::string>;
+            std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
+            RuleT* ptr = ruleObject.get();
+            allRules.emplace_back(std::move(ruleObject));
+            return *ptr;
+        }
+        else if constexpr (numArgs == 4)
+        {
+            using RuleT =
+                TaggedRule<std::string, std::string, std::string, std::string>;
+            std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
+            RuleT* ptr = ruleObject.get();
+            allRules.emplace_back(std::move(ruleObject));
+            return *ptr;
+        }
+        else
+        {
+            using RuleT = TaggedRule<std::string, std::string, std::string,
+                                     std::string, std::string>;
+            std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
+            RuleT* ptr = ruleObject.get();
+            allRules.emplace_back(std::move(ruleObject));
+            return *ptr;
+        }
+        static_assert(numArgs < 5, "Max number of args supported is 5");
     }
 
     void internalAddRuleObject(const std::string& rule, BaseRule* ruleObject)