Как исправить «неправильное количество аргументов шаблона» при включенном C ++ 11? - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть какой-то сложный сторонний код, который использует шаблоны.С 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
       ^~~~~~~~

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

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018
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));
    }
};

Надеюсь, это поможет.

0 голосов
/ 03 декабря 2018

Вы пробовали с 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).

...