Как исправить «неправильное количество аргументов шаблона» при включенном C++ 11?

У меня есть сложный сторонний код, использующий шаблоны. С gcc 7.3.0 он строится нормально, если указан флаг gcc -std = gnu ++ 98, но в противном случае выдает ошибку компиляции (то есть при компиляции C++ 11). Мне нужно исправить компиляцию C++ 11. Вот код (извините, он не полный, но файлы заголовков сложны):

#define CPP11 (__cplusplus > 199711L)

namespace csl
{
namespace PostExec
{

struct Complement
{
    static int64_t Execute(int64_t v)
    {
        return ~v;
    }
};

template<size_t bitWidth, bool maskOutput>
struct Mask
{
    static int64_t Execute(int64_t v)
    {
        return 0;
    }
};

#if CPP11
template<typename P, typename... PS>
struct Compound
{
    template<typename T>
    static T&& Execute(T&& v)
    {
        if (sizeof...(PS) > 0)
        {
            return Compound<PS...>::Execute(P::Execute(std::forward<T>(v)));    <<<< COMPILER ERROR HERE
        }
        return P::Execute(std::forward<T>(v));
    }
};
#else
template<typename P1, typename P2>
struct Compound
{
    static int64_t Execute(int64_t v)
    {
        return P1::Execute(P2::Execute(v));
    }
};
#endif

}
}

using namespace csl;
class CModel
{
public:

    void f1();

private:
    void Execute() { }

    static const size_t PAGE_COUNT = 1;

    static size_t CurrentPage;
    static CPage<1, 0> State[PAGE_COUNT];
};

void CModel::f1()
{
    int64_t n[5];
    StepLogicalNXOr<1, false>::Execute(Page.N[1], n[0], n[1]);
}

size_t CModel::CurrentPage = 0;

CPage <1919, 0> CModel::State[PAGE_COUNT] = {
    CPage <1, 0>()    
};

Ошибка компилятора (когда определен CPP11):

<snip>: error: wrong number of template arguments (0, should be at least 1)
  return Compound<PS...>::Execute(P::Execute(std::forward<T>(v)));
         ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<snip>: note: provided for ‘template<class P, class ... PS> struct csl::PostExec::Compound’
struct Compound
       ^~~~~~~~

Я понимаю, что это сложно, но если кто-нибудь сможет помочь, буду благодарен.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
817
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы пробовали с SFINAE?

Я имею в виду ... что-то вроде (осторожно: код не проверен)

template<typename T>
static typename std::enable_if<0 != sizeof...(PS), T&&>::type Execute(T&& v)
{ return Compound<PS...>::Execute(P::Execute(std::forward<T>(v))); }


template<typename T>
static typename std::enable_if<0 == sizeof...(PS), T&&>::type Execute(T&& v)
 { return P::Execute(std::forward<T>(v)); }

Я имею в виду ... ваш код не может работать, потому что, когда sizeof...(PS) == 0 строка

 return Compound<PS...>::Execute(P::Execute(std::forward<T>(v)));

компилируется, и Compound требует один или более аргументов шаблона; не может принимать нулевой аргумент шаблона.

Я знаю, что эта линия проходит испытания

if (sizeof...(PS) > 0)

а тебе нужен if constexpr

if constexpr (sizeof...(PS) > 0)

чтобы избежать компиляции при ложном тесте; но if constexpr, к сожалению, доступен только начиная с C++ 17.

Итак, единственное решение, которое я вижу в C++ 11, - это разделить метод Execute() на две версии и включить / отключить первую или вторую в соответствии со значением sizeof...(PS).

Спасибо за Ваш ответ. Я попробовал предложенный вами код (ваш первый блок кода), но теперь получаю сообщение об ошибке для строки iq = PostExec :: Compound <PostExec :: Mask <bitWidth, maskOutput>, PostExec :: Complement> :: Execute (BitwiseOps :: XOr :: Выполнить (ia, ib));

DavidA 03.12.2018 12:19

Ошибка: ошибка: вызов перегруженного 'Execute (int64_t)' неоднозначен iq = PostExec :: Compound <PostExec :: Mask <bitWidth, maskOutput>, PostExec :: Complement> :: Execute (BitwiseOps :: XOr :: Execute (ia, ib)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~ ‌ ~~~~~~~~~~~~~~~~~~~~ ‌ ~~~~~~~ ^ ~~~~~~~~ ~~~~ ‌ ~~~~~~~~~~~~~~~~~~~~ ‌ ~

DavidA 03.12.2018 12:20

@DavidA - извините: я забыл ::type после std::enable_if<> для второго случая; Я не знаю, проблема ли в этом (я так не думаю, если честно), но мой первый ответ неверен; ответ исправлен. Можете попробовать с исправленным кодом?

max66 03.12.2018 12:31

Код компилируется с этим изменением. Спасибо. Судя по вашему комментарию к ritesh, вы считаете, что ваше решение более правильное, чем его?

DavidA 03.12.2018 13:20

@DavidA - да, потому что опубликованный вами код намеревается (неправильно) рекурсивно вызывать Execute(), используя типы Ps...; в решении ritesh список шаблонов никогда не меняется: всегда есть P, Ps...; поэтому код компилируется, но (если я не ошибаюсь) вызывает сам себя, пока не будет достигнут предел рекурсии.

max66 03.12.2018 13:53

Спасибо за вашу помощь. Я очень благодарен. Я принял твой ответ.

DavidA 03.12.2018 14:33
Compound<PS...>::Execute(P::Execute(std::forward<T>(v)));

P в приведенном выше вызове является причиной проблемы. Составной шаблон принимает 2 аргумента, и здесь передается только 1.

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

template<typename P, typename... PS>
struct Compound
{
    template<typename T>
    static T&& Execute(T&& v)
    {
        if (sizeof...(PS) > 0)
        {
            return Compound<P,PS...>::Execute(P::Execute(std::forward<T>(v)));   
        }
        return P::Execute(std::forward<T>(v));
    }
};

Я надеюсь, что это помогает.

предотвратить ошибку компилятора, но не использует список P, Ps...

max66 03.12.2018 12:32

Привет, Ритеш, спасибо за ваш ответ, но кажется, что ответ max66 более полный, поэтому я принял это.

DavidA 03.12.2018 14:34

Другие вопросы по теме