Page 1 of 1

Template compilation error w GCC 7.1.0 (ambiguous overload)

Posted: Fri Nov 03, 2017 9:23 pm
by bim
I picked up an old GBA project I would like to finish now. I have a template fixed-point class (ideone example) with tests that compiles with GCC 5.4 (my PC) and 6.3 (IdeOne) and even 7.1 (wandbox), but not the 7.1 included in the current devkitArm. I've tried a couple of things now, but can not get it to work.
GCC always tells me that:

Code: Select all

/src/test.cpp: In function 'int main()':
/src/test.cpp:7:13: error: call of overloaded 'fp(int)' is ambiguous
  fp1616 a0(0);
             ^
In file included from /src/test.cpp:1:0:
/src/test.h:10:2: note: candidate: fp<F>::fp(const float&) [with int F = 16]
  fp(const float & b) : s(b * (1 << F)) { }
  ^~
/src/test.h:9:2: note: candidate: fp<F>::fp(const int32_t&) [with int F = 16; int32_t = long int]
  fp(const int32_t & b) : s(b << F) { }
  ^~
/src/test.h:4:8: note: candidate: constexpr fp<16>::fp(const fp<16>&)
 struct fp
        ^~
Before I go insane: Does anybody have an idea?

Re: Template compilation error w GCC 7.1.0 (ambiguous overlo

Posted: Sun Nov 05, 2017 4:12 pm
by WinterMute
Newlib based toolchains define int32_t as long, literal numbers with no suffix are int. Easiest solution is so use int in your templates instead of int32_t

Re: Template compilation error w GCC 7.1.0 (ambiguous overlo

Posted: Sun Nov 05, 2017 11:20 pm
by mtheall
I made some changes and this seems to work:

Code: Select all

#include <cstdint>
#include <iostream>

template <unsigned F> // changed F to unsigned
struct fp
{
  static_assert(F < 32); // assert shifts are valid

  constexpr static unsigned BITS = F; // change to constexpr static member instead of enum

  int32_t s; // to make sure it's exactly 32-bits wide on any platform

  // this gives the same result for both integral and floating-point types,
  // and the optimizer makes it as efficient as you had before with them separate
  template <typename T>
  fp(const T & b) : s(b * (1 << F)) { }

  // this was fine; delegates to operator=
  // this will be chosen over the previous template because it is more specific
  template<unsigned T>
  fp(const fp<T> & b) { *this = b; }

  // same reason as constructor; no need to have separate integral and floating-point
  // implementations
  template <typename T>
  fp & operator=(const T & b) { s = b * (1 << F); return *this; }

  // removed operator=(const fp &) since it's already covered by this
  template<unsigned T>
  fp & operator=(const fp<T> & b)
  {
    if (T > F) { s = b.s >> (T - F); }
    else if (T < F) { s = b.s << (F - T); }
    else { s = b.s; }
    return *this;
  }

  // removed template argument because it's already implied
  friend std::ostream & operator<<(std::ostream & os, const fp & a) { os << a.s; return os; }
};

using fp824 = fp<24>;
using fp1616 = fp<16>;
using fp248 = fp<8>;

int main() {
  // your code goes here
  fp1616 a0(0);
  fp1616 a1(1);
  fp1616 a2(2);
  fp1616 a3(-2.5f);
  std::cout << a0 << std::endl;
  std::cout << a1 << std::endl;
  std::cout << a2 << std::endl;
  std::cout << a3 << std::endl;
  a0 = 5;
  a0 = 0;
  a0 = 3.4f;
  fp824 b1(1.2f);
  fp1616 b2(b1);
  fp248 b3(b2);
  b1 = b3;
  b1 = b2;
  return 0;
}

Re: Template compilation error w GCC 7.1.0 (ambiguous overlo

Posted: Wed Nov 08, 2017 9:46 am
by bim
Not sure if my previous answer got lost, so:
Thanks for the answers. It was indeed the int vs. int32_t problem. My solution looks something like this atm. I wasn't sure about the compilers capabilities, so the different overloads...