使用函数指针的Specialize模板,取决于模板参数

Pap*_*ter 9 c++ templates function-pointers

我想有一个嵌套值的模板,应该由给定的初始化函数初始化:

template <typename T, T(INIT)()> struct Foo
{
    T value = INIT();
};
Run Code Online (Sandbox Code Playgroud)

它可以这样使用:

// Some random type only instanceable through factory()
struct Bar
{
    int bar{};
private:
    // The only way to create a Bar is through factory()
    friend Bar factory();
    Bar() {};
};

Bar factory() { return {}; }

Foo<Bar, factory> foo;
Run Code Online (Sandbox Code Playgroud)

但是,如果没有提供函数,模板应该尝试默认初始化嵌套值,所以我试图专门化模板:

template <typename T> struct Foo<T, nullptr>
{
    T value{};
};
Run Code Online (Sandbox Code Playgroud)

我的想法是这样使用它:

struct Baz{};

Foo<Bar, factory> foo; // Nested Bar have Bar::bar initialized through factory function.
Foo<Baz>          baz; // No factory function needed, nested Baz default-initialized.
Run Code Online (Sandbox Code Playgroud)

但我刚刚发现模板部分特化类型不能依赖其他模板类型,我得到的错误粘贴在下面:

错误:模板参数'nullptr'的类型'T(*)()'取决于模板参数模板struct Foo


有没有办法实现我的目标?如果它也适用于模板变量会很好:

template <typename T, T(INIT)()> T Foo = INIT();
template <typename T>            T Foo<T, nullptr>{};
Run Code Online (Sandbox Code Playgroud)

额外的问题:为什么部分专业化不能依赖于模板参数?这种限制背后的理由是什么?

Onc*_*lis 2

如果只是在缺少第二个模板参数的情况下进行默认初始化,则可以提供模板化默认初始化函数作为默认参数。

template<typename T> 
    T do_default_assign() { 
        return T(); 
    };                                                                      

template <typename T, T (INIT)() = do_default_assign<T> > struct Foo 
    { 
        T value = INIT(); 
    };
Run Code Online (Sandbox Code Playgroud)

然而,这会遭受不必要的“按值返回”和赋值操作,这对于某些 T 来说可能成本高昂或不可能。