Архитектурный вопрос. Наверху иерархии конфига есть базовый класс, он описывает контракты. В нем должны быть абстрактные методы, допустим getValue и setValue. Если сделать первый как T getValue(T)(string key), то компилятор это разрешает и оно работает, но потомок не может указать override, шаблоны не виртуальные, а без явного переопределения это выглядит неправильным. Поэтому убираю getValue из рутового конфига, там все равно есть специализированные методы для разных значений и он не критичен, проблема отпадает.
Во втором же void setValue(T)(string key, T value) при попадании T в аргумент компилятор сразу начинает рассматривать его как частный случай шаблона в интерфейсе\абстрактном классе - финальный метод, который не может быть абстрактным и должен иметь реализацию, если её представить, то будет вызываться только он, когда как его переопределять должны потомки.
Параметризовать сам класс конфига нельзя, т.к. он рутовый, везде в его использовании будет нужна параметризация. Можно попытаться убрать абстрактность, сделать класс обычным, но, шаблоны все равно не виртуальные и не переопределяются, template mixin тоже выглядит бесполезным. Если обернуть значение в какой-нибудь ConfigValue, то все равно нужно указывать параметризацию. Самый грубый вариант - затереть тип строкой setValue(string, string), но это лишняя конвертация и сильно осложняет валидацию попадающих туда значений и корректную запись в конфиг, хотя если методы будут протект, то тогда потомок может сделать ту же валидацию, но все равно попахивает дичью.
Наиболее логичным выглядит std.variant т.е. setValue(string key, Variant value), но из него get также требует указания типа, получается что для разных типов нужны проверки либо на прямое Variant.type == typeid(foo), либо Variant.convertsTo!(foo), что скорее всего закончится неочевидными граблями или шансом получить в конфиге не то, что хотелось бы, ну и более сложные типы вроде массива\мапы имеют разные типы. Да и при установке значения конфига каждый лишний раз нужно делать присваивание в переменную с Variant, что немного утомляет.
Есть ли еще какие-нибудь более удачные варианты или я не вижу чего-то очевидного?