Search code examples
c++templatescompiler-errorsgmpntl

error: no matching function for call to 'function namel'


My final goal is to compute the power of a quadratic ideal which is implemented as struct variables in C using GMP library.

I have been given a library(ANTL), which contains generic optimized exponentiations using C++ templates, namespaces and NTL. This library does exponentiation for NTL types ZZ_p etc. and basic types like long, float etc..

I have to use the ANTL library to achieve my final goal - computing the power of an ideal, a C struct variable. Since I have never worked with templates and namespaces before I wanted to implement the power of a basic mpz_t variable before to see how everything works.

Now, I have four header files exp.hpp, expbin.hpp, impl.hpp, com.hpp and a main file exp.cpp as follows -

COM.HPP

#ifndef GMPL_COM_H
#define GMPL_COM_H

#include <gmp.h>

namespace GMPL {
    template < class T >
    inline void assign(T C, const T A)
    {
        mpz_set(C, A);
    }

    template<class T>
    void mul (T C, const T A, const T B)
    {
        mpz_mul(C, A, B);
    }

    template<class T>
    void sqr (T C, const T A)
    {
        mpz_mul(C, A, A);
    }

}
#endif // guard

EXP.HPP

#ifndef EXP_H
#define EXP_H

#include "com.hpp"

namespace GMPL
{
    template < class T >
    class exp
    {
        public:
        exp() {};
        virtual ~exp() {};

        virtual void power (T C, const T A, const NTL::ZZ & n) = 0;
    };

} // GMPL

#endif // EXP_H

EXPBIN.HPP

#ifndef EXPBIN_H
#define EXPBIN_H

#include "exp.hpp"

namespace GMPL
{
    template < class T >
    class expbin : public exp<T>
    {
        public:
        expbin() {};
        ~expbin() {};

        void power (T C, const T A, const NTL::ZZ & n);
    };

} // GMPL

// Unspecialized template definitions.
#include "impl.hpp"

#endif // EXPBIN_H

IMPL.HPP

using namespace GMPL;

//
// compute A^n using standard left-to-right binary method
//
template < class T > 
void expbin<T>::power (T C, const T A, const NTL::ZZ & n)
{
    assign(C,A);
    for (register long i = NumBits(n)-2 ; i >= 0 ; i--)
    {
        sqr(C, C);
        if (bit(n, i) == 1)
            mul(C, C, A);
    }
}

EXP.CPP

#include <NTL/lzz_p.h>
#include <gmp.h>

namespace GMPL {}
using namespace GMPL;


#include "expbin.hpp"

NTL_CLIENT

int main ()
{
    // NTL variables
    ZZ n;

    // GMP variables
    mpz_t aa;
    mpz_t bb;
    mpz_init(aa);
    mpz_init(bb);

    // generate random exponent of size 512 bits
    RandomLen (n, 512); // NTL function

    // initialize exponentiation classes
    expbin<mpz_t> obj;

    // compute a^n with available methods
    obj.power (bb,aa,n);

    // check and output results
    gmp_printf("%Zd", bb);
}

when I try to compile EXP.CPP using (as mentioned on Victor Shoup's NTL documentation online)

g++ -g -O2 -std=c++11 -pthread -march=native exp.cpp -o t -lntl -lgmp -lm

I get the following error messages-

$ g++ -g -O2 -std=c++11 -pthread -march=native exp.cpp -o t -lntl -lgmp -lm
In file included from exp.cpp:8:
In file included from ./expbin.hpp:46:
./impl.hpp:16:10: warning: 'register' storage class specifier is deprecated and
      incompatible with C++1z [-Wdeprecated-register]
    for (register long i = NumBits(n)-2 ; i >= 0 ; i--)
         ^~~~~~~~~
./impl.hpp:15:5: error: no matching function for call to 'assign'
    assign(C,A);
    ^~~~~~
exp.cpp:28:9: note: in instantiation of member function
      'GMPL::expbin<__mpz_struct [1]>::power' requested here
    obj.power (bb,aa,n);
        ^
./com.hpp:16:17: note: candidate template ignored: deduced conflicting types for
      parameter 'T' ('__mpz_struct *' vs. 'const __mpz_struct *')
    inline void assign(T C, const T A)
                ^
In file included from exp.cpp:8:
In file included from ./expbin.hpp:46:
./impl.hpp:20:13: error: no matching function for call to 'mul'
            mul(C, C, A);
            ^~~
./com.hpp:22:10: note: candidate template ignored: deduced conflicting types for
      parameter 'T' ('__mpz_struct *' vs. 'const __mpz_struct *')
    void mul (T C, const T A, const T B)

Assiduous googling about these errors shows that one has to have an empty constructor in the parent class but I already have it.

I know the compile statement is correct because other than that nothing else works when using NTL. At this point I ran out of ideas to fix this. Thanks in advance.

EDIT This question has been resolved. I wish for this question to be closed or removed.


Solution

  • One solution would be to not use templates for your function wrappers. It seems like there would be only one template parameter that ever makes sense (i.e. T replaced by mpz_t), given that the template parameter has to be compatible with mpz_set. Templates seem like the wrong tool for the job. Just define your wrappers taking parameters of type mpz_t and const mpz_t:

    inline void assign(mpz_t C, const mpz_t A)
    {
        mpz_set(C, A);
    }
    

    You did say you wanted to learn templates, but using them in an inappropriate context is not going to be that helpful. And you still have the templates for your classes to learn from.

    That being said, I can interpret the compiler messages for you.


    warning: 'register' storage class specifier is deprecated and incompatible with C++1z [-Wdeprecated-register]
    for (register long i = NumBits(n)-2 ; i >= 0 ; i--)

    This is an easy one to fix. Get rid of "register" in that line. It is no longer a performance optimization.

    error: no matching function for call to 'assign'
    assign(C,A);
    [...]
    note: candidate template ignored: deduced conflicting types for parameter 'T'

    The compiler is having trouble figuring out what to use as the template parameter in this function call. There are two function arguments, each implying what the template parameter for assign should be. (This is distinct from the template parameter for expbin, even though both are named T.) It's a problem when the implications are in conflict. One way to make this work should be to specify what you want the parameter to be, as in

    assign<T>(C, A);
    

    This makes it explicit that the template parameter for assign (given between < and >) is supposed to be the template parameter for expbin (the meaning of T in this context).

    Note: The templates you defined look like they might normally work without having to specify T like this. However, mpz_t is technically an array of one structure (not simply a structure), and arrays used as arguments can decay, which can lead to type confusion.

    error: no matching function for call to 'mul'
    mul(C, C, A);
    note: candidate template ignored: deduced conflicting types for parameter 'T'

    Same (although in this case there are three function arguments, so three deduced candidates for T).

    mul<T>(C, C, A);