0

I have developed a templated library for some computations that I need to do. Now, I need to use it in conjunction with Ceres and I want to be able to use the automatic derivaties tool. The requirement for this is that the functions and classes used need to be templated so Ceres can use its ceres::Jet<T,n> type. I have been able to develop functions and use them and ceres for solving a minimization problem. However, my library (which consists of a good amount of functions and classes) have some functions like (please, note that this is a simplified example that produces the same error as the one I am having with ceres::Jet<T,n> in my library):

template <typename T>
void func()
{
  T a = 2;
}

I created a small structure that emulates the cres::Jet<T,N> one (this example struct has the same constructors as ceres::Jet<T,N>):

template <typename T, int N>
struct A
{
  enum
  {
    DIMENSION = N
  };

  A()
  {
  }

  explicit A(const T& value)
  {
  }

  A(const T& value, int k)
  {
  }
};

Whenever I do func<A<double,2>>() (or any T and N) I get the following error:

error: no viable conversion from 'int' to 'A<double, 2>'
  T a = 2;
    ^   ~

I know I can change T a = 2 to T a = T(2) and it will work. However, I don't want to change this in every place in my library (It would take a long time) unless T a = 2 is some really stupid thing that I should not be doing. I have tried to add constructors or operator= without any success (the operator= does not even compile):

template <typename M>
A(const M& a)
{
}

template <typename M>
A& operator=(const M& other)
{
  return A<T, N>(T(other));
}

I have also been trying to understand my problem by reading implicit conversion and user-defined conversions but I do not understand how to use that information in my example.

My questions are:

  1. Is there a way that I can do that by adding some definition to the class?
  2. Is there a way that I can do that without adding some definition in the class?

Thank you very much.

apalomer
  • 1,895
  • 14
  • 36
  • 1
    By using `explicit` you are saying that you do not want that constructor to participate in implicit conversions, which seems to be what you are trying to do. – François Andrieux Sep 13 '18 at 00:33
  • 3
    `operator=` should be altering `this`. It should not be trying to construct a new instance. Even if creating a new instance is what you want from `operator=`, returning that new instance by reference is incorrect and leads to returning dangling reference. Your new `A` is destroyed at the end of the operator. – François Andrieux Sep 13 '18 at 00:35
  • Thank you @FrançoisAndrieux for your answer, that totally solved it. Is there a solution that I can do outside of the class as well? The `operator=` is just an example of things that I've tried. It is not part of `ceres::Jet`. – apalomer Sep 13 '18 at 00:35
  • 1
    I can't think of any way to provide new implicit conversions without changing one of the `class`s involved in the conversion. – François Andrieux Sep 13 '18 at 00:36
  • Can you think of any good reason why the `explicit` specifier might be int he `ceres::Jet` constructor? (I have also asked to the developers of ceres if there is any design reason for that) – apalomer Sep 13 '18 at 00:53
  • This [so response](https://stackoverflow.com/a/121163/4179302) is a good additional information – apalomer Sep 13 '18 at 00:58
  • 2
    It's generally seen as a good habit to `explicit` any constructor with a single argument (move and copy constructors not withstanding), unless the design specifically calls for implicit conversions. Implicit conversions can be dangerous because they can lead to unexpected or surprising behavior or can hide what would otherwise be easy to spot errors. So it's no surprise that they are `explicit`, it's usually the "default" thing to do unless there's a good reason not to use it. – François Andrieux Sep 13 '18 at 00:58

0 Answers0