Тип класса в зависимости от типа шаблона

Есть один подлый случай, когда return в обычном методе и return await в async метод ведут себя по-разному: в сочетании с using (или, более общо, любой return await в блоке try), .

Рассмотрим эти две версии метода:

Task<SomeResult> DoSomethingAsync()
{
    using (var foo = new Foo())
    {
        return foo.DoAnotherThingAsync();
    }
}

async Task<SomeResult> DoSomethingAsync()
{
    using (var foo = new Foo())
    {
        return await foo.DoAnotherThingAsync();
    }
}

Первый метод будет Dispose() объектом Foo, как только метод DoAnotherThingAsync() вернется, что вероятно, задолго до его завершения. Это означает, что первая версия, вероятно, глючит (потому что Foo находится слишком рано), а вторая версия будет работать нормально.

3
задан Stack Danny 22 February 2019 в 12:05
поделиться

3 ответа

Вы можете справиться с этим с некоторой чертой. Определите

// Primary template
template <class T>
struct Table_Trait;

// Specialization
template <>
struct Table_Trait<int> { using type = Table_Inside_int; };

template <>
struct Table_Trait<char> { using type = Table_Inside_char; };

template <class T>
using Table_Inside_t = typename Table_Trait<T>::type;

и используйте его через

template<class T>
class Table {
    Table_Inside_t *tmp;
};

Однако, может быть более простое решение, если нет необходимости иметь независимые классы Table_Inside_int и Table_Inside_double. Вы можете использовать специализацию также непосредственно

// Primary template
template <class T>
class Table_Inside;

// Specialization
template <>
class Table_Inside<int> { /* implementation for int */ };

template <>
class Table_Inside<char> { /* implementation for char */ };
0
ответ дан Handy999 22 February 2019 в 12:05
поделиться

Это легко сделать с помощью специализации :

// The "base" generic case
template<typename T>
class Table_Inside;

template<>
class Table_Inside<char>
{
    // Special implementation for characters
};

template<>
class Table_Inside<int>
{
    // Special implementation for integers
};

template<typename T>
class Table
{
    Table_Inside<T>* tmp;
};

Если вам нужна общая функциональность, совместно используемая классами char и int, то вы можете использовать наследование для этого .

0
ответ дан Some programmer dude 22 February 2019 в 12:05
поделиться

Если специализация не совсем работает и существует только пара типов, псевдоним можно создать, используя std::conditional и std::is_same :

// assumes only char or int will be passed
template <class T>
using Table_Inside = std::conditional_t<std::is_same_v<T, char>, Table_Inside_char, Table_Inside_int>;
[ 117] Это можно использовать так же, как и раньше, как Table_Inside<T>.

0
ответ дан kmdreko 22 February 2019 в 12:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: