Вам не нужен первый template<>
по частичной специализации test<C<D>>
.Более того, вы можете только частично специализировать шаблоны классов, а не шаблоны функций.Примерно так может сработать:
template <class X>
struct thing
{
static void test() { cout << "This is a test" << endl;}
};
template <int D>
struct thing<C<D>>
{
static void test() {cout << C<D>::foo() << endl;}
};
Если шаблон вашей функции принял аргумент и использовал его для вывода аргумента шаблона, то вы могли бы получить аналогичный эффект, используя перегрузку, например:
template <class X>
void test(const X&) { cout << "This is a test" << endl;}
template <int D>
void test(const C<D>&) {cout << C<D>::foo() << endl;}
test(3); // calls first version
test(C<3>()); // calls second version