СФИНАЕ это позволяет? - PullRequest
       17

СФИНАЕ это позволяет?

2 голосов
/ 19 сентября 2019

Я пытаюсь удалить функции-члены из шаблона класса, используя std :: enable_if.Когда я отключаю функцию, я получаю сообщение об ошибке:

C2938: 'std::enable_if_t<false,int64_t>' : Failed to specialize alias template

Мой код выглядит так:

template<int NUM_COMPONENTS>
struct Foo
{
    typename std::enable_if_t<(NUM_COMPONENTS == 2), void> set(int64 x, int64 y)
    {
        // some code here
    }
}

Я делаю что-то, что не разрешено стандартом, если это такдругой способ сделать это?Или это ошибка?Я использую MSVC с QtCreator.

Ответы [ 2 ]

4 голосов
/ 19 сентября 2019

S в SFINAE означает замену аргументов шаблона для параметров шаблона, что делается для шаблона , когда он рассматривается в качестве кандидата для разрешения перегрузки.

Foo являетсяшаблон, но set нет.В результате вы создаете экземпляр Foo, который создает объявление set, а функция содержит недопустимый тип возвращаемого значения.Не нужно иметь SFINAE, потому что этот бит замещения не происходит до разрешения перегрузки.

Чтобы применить SFINAE, вы должны сделать set шаблоном:

template<int NUM = NUM_COMPONENTS>
std::enable_if_t<(NUM== 2), void> set(int64 x, int64 y)
{
    // some code here
}

СейчасВы получаете действительное объявление (шаблона).Но когда вы попытаетесь вызвать , произойдет другая замена, к которой применяется SFINAE.

В качестве бонуса, C ++ 20 делает это упражнение спорным.То, чего вы хотите достичь, станет возможным с помощью простого предложения requires:

void set(int64 x, int64 y) requires (NUM_COMPONENTS == 2)
{
    // some code here
}
1 голос
/ 19 сентября 2019

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

void set(int x, int y)
{
    static_assert(NUM_COMPONENTS == 2);
}
...