簡體   English   中英

模板靜態函數模板類類型推導

[英]template static function template class type deduction

我想在單調模板類中創建靜態函數,這樣就可以扣除模板類的類型。 問題是,從模板類調用靜態函數需要顯式類型。 我想出的唯一解決方法是模板函數,而不是模板成員函數。

這是一個例子。 問題是 foo4 部分不起作用

template <class T>
class Foo
{
private:
    Foo() {}
    Foo(const Foo&) = delete;
    Foo& operator= (const Foo&) = delete;

public:
    static auto& Instance()
    {
        static Foo foo{};
        return foo;
    }

    template<class K> static
    auto& DeductInstance(const K&)
    {
        static Foo<K> foo{};
        return foo;
    }

};

template<class K>
auto& DeductInstance(const K&)
{
    return Foo<K>::Instance();
}

void main()
{
    auto& foo1 = Foo<int>::Instance(); //OK
    auto& foo2 = Foo<int>::Instance(); //OK (return same example as foo1)
    auto& foo3 = DeductInstance(123); //OK
    auto& foo4 = Foo::DeductInstance(123); //NOT WORKING
}

從理論上講,您可以使用注入的類名來請求語法。 這會使Foo::解析為特定的,不相關的Foo<x>:: 這是一個例子:

struct BaseFoo {
    template<class K> static
    auto& DeductInstance(const K&);
};

template <class T>
struct Foo  {
    static auto& Instance() {
        static Foo foo{};
        return foo;
    }
};

template<>
struct Foo<void> : private BaseFoo {
    using BaseFoo::DeductInstance;
};

template<typename K>
auto& BaseFoo::DeductInstance(const K&)
{
    return Foo<K>::Instance();
}

using MakeFooAvailable = Foo<void>;

struct Dummy : MakeFooAvailable {
    auto& bar() {
        // Syntax working
        return Foo::DeductInstance(234);
    }
};

Dummy類中,為基類Foo注入了一個類名,將其解析為Foo<void> 然后, Foo<void>使BaseFoo::DeductInstance在其范圍內可用於名稱解析。


我建議不要使用此解決方案,因為它是一個聰明的解決方案。 聰明通常意味着令人驚訝。 程序員不希望將Foo視為非模板。 我認為最好的解決方案是:

auto& foo1 = Foo<int>::Instance(); //OK

越簡單越好。

我必須承認,我不完全理解您要做什么。 但是,您可以執行以下兩個操作之一:

struct foo {
    template <typename T> 
    static T deduce(const T& t) { 
        return {};
    }
};

template <typename T> 
T deduce_free(const T& t) {
    return {};
}

int main() {
    auto x = foo::deduce(1);
    auto y = deduce_free(1);
}

但是,在知道T是什么之前,您無法在bar<T>某些實例上調用方法(是否為靜態)。

事情已經改變,與C ++ 17位具有類模板參數推導 ,但 據我知道這個工程的建設者,所以你仍然需要一個 foo<int>第一之前,你可以調用一個 foo<int>::deduce() 我對此沒有經驗,所以說不出什么錯;)。

現在是 2021 年,我們有 CTAD,但我認為它沒有幫助。 我認為這非常接近你(和我!)想要的:

// A helper struct to provide Foo with a default template 
// that isn't useful for instantiation:
struct DoNotInstantiate { DoNotInstantiate() = delete; };

template <class T = DoNotInstantiate>
class Foo
{
private:
    Foo() {
        static_assert(!std::is_same_v<T, DoNotInstantiate>, "You can't actually instantiate it with the default, it's just to make the static function work."); // Optional
    }
    // ...

public:
    // ...

    template<class K> static
    auto& DeductInstance(const K&)
    {
        static Foo<K> foo{};
        return foo;
    }
};

所以你可以調用Foo<>::DeduceInstance(bar); . 您仍然必須編寫<>但除此之外,我認為它是完美的。

如果您不希望那樣並且真的希望能夠在模板上調用靜態,僅命名模板名稱,則可以使用以下方法:

template <template<typename ...> class FooType, typename T>
auto DeduceInstance(const T& x) {
    return FooType<T>::DeduceInstance(x);
}

這讓您可以調用DeduceInstance<Foo>(x) ,其中Foo只是一個模板。 但這感覺是圓的。 我更喜歡Foo<>::DeduceInstance(x); .

如果 CTAD 讓你寫就好了

template <class T>
Foo::DeductInstance(const T&) -> T&;

或者它可能是

template <class T>
Foo::DeductInstance(const T&) -> Foo<T>::DeduceInstance(const T&);

或類似的東西,基本上是說如果您使用沒有類型的模板名稱來調用靜態,請使用參數列表來摻雜調用者正在談論的模板。

暫無
暫無

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

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