шаблон статическая функция шаблон класса тип удержания - PullRequest
0 голосов
/ 13 марта 2019

Я хочу сделать статическую функцию в шаблонном классе синглетного типа, которая бы могла выводить типы шаблонного класса. Проблема в том, что для вызова статической функции из класса шаблона требуется явный тип. Единственный обходной путь, к которому я пришел, - это функция шаблона вместо функции-члена шаблона.

Вот пример. Проблема в том, что часть 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
}

Ответы [ 2 ]

1 голос
/ 13 марта 2019

Синтаксис, который вы запрашиваете, теоретически возможен с использованием введенных имен классов.Это заставит 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

Чем проще, тем лучше.

0 голосов
/ 13 марта 2019

Я должен признать, что я не совсем понимаю, что вы пытаетесь сделать.Однако вы можете выполнить одно из следующих двух действий:

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);
}

Но вы не можете вызвать метод (статический или нет) для некоторого экземпляра bar<T>, прежде чем узнаете, что такое T.

С C ++ 17 все немного изменилось: вычет аргументов шаблона класса , хотя , насколько я знаю, это работает для конструкторов, так что вам все равно нужен foo<int> сначала, прежде чем вы могли бы позвонить foo<int>::deduce() Я слишком неопытен с этим, чтобы сказать что-то не так;).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...