Я пытаюсь использовать метапрограммирование шаблона, чтобы найти наибольший общий делитель, но компилятор сообщает об ошибке - PullRequest
0 голосов
/ 05 августа 2020

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

Код C ++:

#include <iostream>
namespace meta{
    namespace _algorithm{
        template<bool size_,long long A_,long long B_>
        struct GCD{
            static const long long value;
        };
        template<bool size_,long long A_>
        struct GCD<size_,A_,0>{
            static const long long value=A_;
        };
        template<bool size_,long long B_>
        struct GCD<size_,0,B_>{
            static const long long value=B_;
        };
        template<long long A_,long long B_>
        struct GCD<false,A_,B_>{
            static const long long value=GCD<false,B_,A_%B_>::value;
        };
        template<long long A_,long long B_>
        struct GCD<true,A_,B_>{
            static const long long value=GCD<true,B_%A_,A_>::value;
        };
    }
}
using namespace std;
int main(){
    cout<<meta::_algorithm::GCD<1346<540,1346,540>::value<<endl;
}

Операционная система: Linux(Ubuntu 20.04.1 LTS)

Компилятор: GCC10.1.0

Команда компиляции: $ g++ main.cpp -std=20

Сообщение об ошибке:

basictype.hpp: In instantiation of ‘const long long int meta::_algorithm::GCD<false, 8, 2>::value’:
basictype.hpp:26:63:   recursively required from ‘const long long int meta::_algorithm::GCD<false, 540, 266>::value’
basictype.hpp:26:63:   required from ‘const long long int meta::_algorithm::GCD<false, 1346, 540>::value’
basictype.hpp:127:53:   required from here
basictype.hpp:26:63: 错误:ambiguous template instantiation for ‘struct meta::_algorithm::GCD<false, 2, 0>’
   26 |             static const long long value=GCD<false,B_,A_%B_>::value;
      |                                                               ^~~~~
basictype.hpp:17:16: 附注:备选是: ‘template<bool size_, long long int A_> struct meta::_algorithm::GCD<size_, A_, 0> [with bool size_ = false; long long int A_ = 2]’
   17 |         struct GCD<size_,A_,0>{
      |                ^~~~~~~~~~~~~~~
basictype.hpp:25:16: 附注:         ‘template<long long int A_, long long int B_> struct meta::_algorithm::GCD<false, A_, B_> [with long long int A_ = 2; long long int B_ = 0]’
   25 |         struct GCD<false,A_,B_>{
      |                ^~~~~~~~~~~~~~~~
basictype.hpp:26:63: 错误:嵌套名指定中使用了不完全的类型‘meta::_algorithm::GCD<false, 2, 0>’
   26 |             static const long long value=GCD<false,B_,A_%B_>::value;
      |                                                               ^~~~~

Кто-нибудь знает, почему это происходит?

Ответы [ 2 ]

1 голос
/ 05 августа 2020

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

#include <iostream>

template<long long A, long long B> struct GCD;

template<long long A> struct GCD<A,0> {
  static const long long value=A;
};

template<long long A,long long B> struct GCD {
  static const long long value=GCD<B,A%B>::value;
};

int main(){
  std::cout << GCD<1989,867>::value << std::endl;
}

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

0 голосов
/ 05 августа 2020
    template<long long A_,long long B_, bool ABigger=(A_>=B_)>
    struct GCD;
    template<long long A_>
    struct GCD<A_,0, true>{
        static const long long value=A_;
    };
    template<long long B_>
    struct GCD<0,B_, false>{
        static const long long value=B_;
    };
    template<long long A_,long long B_>
    struct GCD<A_,B_,true>{
        static const long long value=GCD<A_%B_, B_>::value;
    };
    template<long long A_,long long B_>
    struct GCD<A_,B_,false>{
        static const long long value=GCD<A_,B_%A_>::value;
    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...