簡體   English   中英

使用函數指針的Specialize模板,取決於模板參數

[英]Specialize template with function pointer, that depends on template parameter

我想有一個嵌套值的模板,應該由給定的初始化函數初始化:

template <typename T, T(INIT)()> struct Foo
{
    T value = INIT();
};

它可以這樣使用:

// 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;

但是,如果沒有提供函數,模板應該嘗試默認初始化嵌套值,所以我試圖專門化模板:

template <typename T> struct Foo<T, nullptr>
{
    T value{};
};

我的想法是這樣使用它:

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.

但我剛剛發現模板部分特化類型不能依賴其他模板類型,我得到的錯誤粘貼在下面:

錯誤:模板參數'nullptr'的類型'T(*)()'取決於模板參數模板struct Foo


有沒有辦法實現我的目標? 如果它也適用於模板變量會很好:

template <typename T, T(INIT)()> T Foo = INIT();
template <typename T>            T Foo<T, nullptr>{};

額外的問題:為什么部分專業化不能依賴於模板參數? 這種限制背后的理由是什么?

對於您的情況,您可以使用:

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

template <typename T, T(INIT)() = &default_construct<T>>
struct Foo
{
    T value = INIT();
};

然后使用它像:

Foo<int> f;
Foo<int, bar> b;

現場演示

如果只是在缺少第二個模板參數的情況下進行默認初始化,則可以提供模板化的默認初始化函數作為默認參數。

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

template <typename T, T (INIT)() = do_default_assign<T> > struct Foo 
    { 
        T value = INIT(); 
    };

然而,這會遭受不必要的“按價值返回”和分配操作,這對於某些人而言可能是昂貴的或不可能的。

您可以定義一個constructor模板函數,該函數將初始化Type的值,然后將其用作默認構造函數:

template<typename Type, typename... Args>
Type constructor(Args... args) { 
    return Type(std::forward<Args>(args)...);
}

然后將其用作函數的默認模板參數:

template <typename T, T(INIT)() = constructor<T>> struct Foo
{
    T value = INIT();
};

現場演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM