How to implicitly convert class template object when passing as argument to function template?












1















Considering the following small code snippet:



template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>(){ /* implicit/explicit cast to std::vector */ }
};

template <typename T = float>
void myFunc(const std::vector<T>& _arg){
printf("myFuncn");
}

int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
}


When trying to compile, I get the error



template argument deduction/substitution failed: [...]  ‘A<int>’ is not derived from ‘const std::vector<T>’


While, on the other hand, if myFunc is not a template, it will compile and run just fine. I assume the error is caused by the fact that since myFunc accepts multiple vector types as argument, the compiler does not know to what type it should convert foo to. However, shouldn't the default template values be used as fallback in such case? Is there an alternative way to be able to pass an object of class A to myFunc?










share|improve this question




















  • 2





    No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.

    – NathanOliver
    Nov 21 '18 at 17:30






  • 3





    please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear how myFunc and A are related.

    – user463035818
    Nov 21 '18 at 17:31











  • @NathanOliver If myFunc is untemplated and takes, for instance, an std::vector<float> as argument, foo is cast implicitely. Shouldn't the default value for myFunc template (float) be used then?

    – joaocandre
    Nov 21 '18 at 17:37











  • @user463035818 I've added a small main() to reproduce the error. A and myFunc aren't related.

    – joaocandre
    Nov 21 '18 at 17:38











  • The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as operator std::vector<T>() and you will still get the same error. You can make the entire class A non-template either andbut makes no difference, still the same error.

    – n.m.
    Nov 21 '18 at 18:09


















1















Considering the following small code snippet:



template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>(){ /* implicit/explicit cast to std::vector */ }
};

template <typename T = float>
void myFunc(const std::vector<T>& _arg){
printf("myFuncn");
}

int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
}


When trying to compile, I get the error



template argument deduction/substitution failed: [...]  ‘A<int>’ is not derived from ‘const std::vector<T>’


While, on the other hand, if myFunc is not a template, it will compile and run just fine. I assume the error is caused by the fact that since myFunc accepts multiple vector types as argument, the compiler does not know to what type it should convert foo to. However, shouldn't the default template values be used as fallback in such case? Is there an alternative way to be able to pass an object of class A to myFunc?










share|improve this question




















  • 2





    No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.

    – NathanOliver
    Nov 21 '18 at 17:30






  • 3





    please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear how myFunc and A are related.

    – user463035818
    Nov 21 '18 at 17:31











  • @NathanOliver If myFunc is untemplated and takes, for instance, an std::vector<float> as argument, foo is cast implicitely. Shouldn't the default value for myFunc template (float) be used then?

    – joaocandre
    Nov 21 '18 at 17:37











  • @user463035818 I've added a small main() to reproduce the error. A and myFunc aren't related.

    – joaocandre
    Nov 21 '18 at 17:38











  • The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as operator std::vector<T>() and you will still get the same error. You can make the entire class A non-template either andbut makes no difference, still the same error.

    – n.m.
    Nov 21 '18 at 18:09
















1












1








1








Considering the following small code snippet:



template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>(){ /* implicit/explicit cast to std::vector */ }
};

template <typename T = float>
void myFunc(const std::vector<T>& _arg){
printf("myFuncn");
}

int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
}


When trying to compile, I get the error



template argument deduction/substitution failed: [...]  ‘A<int>’ is not derived from ‘const std::vector<T>’


While, on the other hand, if myFunc is not a template, it will compile and run just fine. I assume the error is caused by the fact that since myFunc accepts multiple vector types as argument, the compiler does not know to what type it should convert foo to. However, shouldn't the default template values be used as fallback in such case? Is there an alternative way to be able to pass an object of class A to myFunc?










share|improve this question
















Considering the following small code snippet:



template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>(){ /* implicit/explicit cast to std::vector */ }
};

template <typename T = float>
void myFunc(const std::vector<T>& _arg){
printf("myFuncn");
}

int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
}


When trying to compile, I get the error



template argument deduction/substitution failed: [...]  ‘A<int>’ is not derived from ‘const std::vector<T>’


While, on the other hand, if myFunc is not a template, it will compile and run just fine. I assume the error is caused by the fact that since myFunc accepts multiple vector types as argument, the compiler does not know to what type it should convert foo to. However, shouldn't the default template values be used as fallback in such case? Is there an alternative way to be able to pass an object of class A to myFunc?







c++ class templates casting implicit-conversion






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 17:48









YSC

25.5k557112




25.5k557112










asked Nov 21 '18 at 17:28









joaocandrejoaocandre

5051124




5051124








  • 2





    No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.

    – NathanOliver
    Nov 21 '18 at 17:30






  • 3





    please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear how myFunc and A are related.

    – user463035818
    Nov 21 '18 at 17:31











  • @NathanOliver If myFunc is untemplated and takes, for instance, an std::vector<float> as argument, foo is cast implicitely. Shouldn't the default value for myFunc template (float) be used then?

    – joaocandre
    Nov 21 '18 at 17:37











  • @user463035818 I've added a small main() to reproduce the error. A and myFunc aren't related.

    – joaocandre
    Nov 21 '18 at 17:38











  • The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as operator std::vector<T>() and you will still get the same error. You can make the entire class A non-template either andbut makes no difference, still the same error.

    – n.m.
    Nov 21 '18 at 18:09
















  • 2





    No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.

    – NathanOliver
    Nov 21 '18 at 17:30






  • 3





    please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear how myFunc and A are related.

    – user463035818
    Nov 21 '18 at 17:31











  • @NathanOliver If myFunc is untemplated and takes, for instance, an std::vector<float> as argument, foo is cast implicitely. Shouldn't the default value for myFunc template (float) be used then?

    – joaocandre
    Nov 21 '18 at 17:37











  • @user463035818 I've added a small main() to reproduce the error. A and myFunc aren't related.

    – joaocandre
    Nov 21 '18 at 17:38











  • The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as operator std::vector<T>() and you will still get the same error. You can make the entire class A non-template either andbut makes no difference, still the same error.

    – n.m.
    Nov 21 '18 at 18:09










2




2





No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.

– NathanOliver
Nov 21 '18 at 17:30





No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.

– NathanOliver
Nov 21 '18 at 17:30




3




3





please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear how myFunc and A are related.

– user463035818
Nov 21 '18 at 17:31





please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear how myFunc and A are related.

– user463035818
Nov 21 '18 at 17:31













@NathanOliver If myFunc is untemplated and takes, for instance, an std::vector<float> as argument, foo is cast implicitely. Shouldn't the default value for myFunc template (float) be used then?

– joaocandre
Nov 21 '18 at 17:37





@NathanOliver If myFunc is untemplated and takes, for instance, an std::vector<float> as argument, foo is cast implicitely. Shouldn't the default value for myFunc template (float) be used then?

– joaocandre
Nov 21 '18 at 17:37













@user463035818 I've added a small main() to reproduce the error. A and myFunc aren't related.

– joaocandre
Nov 21 '18 at 17:38





@user463035818 I've added a small main() to reproduce the error. A and myFunc aren't related.

– joaocandre
Nov 21 '18 at 17:38













The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as operator std::vector<T>() and you will still get the same error. You can make the entire class A non-template either andbut makes no difference, still the same error.

– n.m.
Nov 21 '18 at 18:09







The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as operator std::vector<T>() and you will still get the same error. You can make the entire class A non-template either andbut makes no difference, still the same error.

– n.m.
Nov 21 '18 at 18:09














3 Answers
3






active

oldest

votes


















1














Implicit conversions are not considered when attempting to deduce template parameters. Since A<int> cannot match const std::vector<T>, the myFunc template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).



For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.






share|improve this answer































    1














    The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo) the compiler is unable to determine a type for T. And that's really the end of the story.



    See Template argument deduction on C++ reference.



    Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.



    See "C++ Function Templates: How Do They Really Work?" on youtube.






    share|improve this answer































      0














      As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc and do an explicit cast. Consider the following code:



      #include <vector>
      #include <iostream>

      template <typename T>
      class A{
      public:
      A() { };
      ~A() { };
      // ...
      template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
      std::cout << "I am doing a conversion" << std::endl;
      return std::vector<outT>(); }
      };

      template <typename T = float, typename... Args>
      void myFunc(const std::vector<T, Args...>& _arg){
      std::cout << "myFunc" << std::endl;
      }

      template <typename T>
      void myFunc(const A<T>& _arg)
      {
      std::cout << "I am the second variant of myFunc" << std::endl;
      myFunc(static_cast<const std::vector<T>>(_arg));
      }

      int main(int argc, char const *argv) {
      A<int> foo;
      std::cout << "-- First call of myFunc" << std::endl;
      myFunc(foo);
      std::cout << "-- Second call of myFunc" << std::endl;
      std::vector<double> x = foo;
      myFunc(x);

      return 0;
      }


      Output of the program is:



      -- First call of myFunc
      I am the second variant of myFunc
      I am doing a conversion
      myFunc
      -- Second call of myFunc
      I am doing a conversion
      myFunc


      When you pass foo to myFunc the compiler uses the second overload of myFunc which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo to a std::vector, hence doing the conversion before passing the resulting std::vector to the first overload of myFunc. Notice that:




      • you need a const conversion operator if you wnat to keep constness in the overloads of myFunc.


      • you need an additional template parameter pack typename... Args in the first overload of myFunc to capture every specialization of std::vector (say, with a custom allocator).



      Another option could be to declare A as class derived from std::vector. Something like the following code:



      #include <vector>
      #include <iostream>

      template <typename T>
      class A : public std::vector<T> {
      public:
      A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
      };

      template <typename T = float, typename... Args>
      void myFunc(const std::vector<T, Args...>& _arg){
      std::cout << "myFunc" << std::endl;
      }

      int main(int argc, char const *argv) {
      A<int> foo;
      myFunc(foo);

      return 0;
      }


      In this case you do not need a conversion and you call myFunc by slicing. A drawback to this approach is that you do the conversion to a std::vector in the constructor and, every time you modify A, you must keep the data of the base class std::vector up to date.






      share|improve this answer
























        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53417606%2fhow-to-implicitly-convert-class-template-object-when-passing-as-argument-to-func%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        1














        Implicit conversions are not considered when attempting to deduce template parameters. Since A<int> cannot match const std::vector<T>, the myFunc template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).



        For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.






        share|improve this answer




























          1














          Implicit conversions are not considered when attempting to deduce template parameters. Since A<int> cannot match const std::vector<T>, the myFunc template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).



          For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.






          share|improve this answer


























            1












            1








            1







            Implicit conversions are not considered when attempting to deduce template parameters. Since A<int> cannot match const std::vector<T>, the myFunc template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).



            For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.






            share|improve this answer













            Implicit conversions are not considered when attempting to deduce template parameters. Since A<int> cannot match const std::vector<T>, the myFunc template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).



            For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 21 '18 at 18:03









            Max LanghofMax Langhof

            11.9k22241




            11.9k22241

























                1














                The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo) the compiler is unable to determine a type for T. And that's really the end of the story.



                See Template argument deduction on C++ reference.



                Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.



                See "C++ Function Templates: How Do They Really Work?" on youtube.






                share|improve this answer




























                  1














                  The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo) the compiler is unable to determine a type for T. And that's really the end of the story.



                  See Template argument deduction on C++ reference.



                  Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.



                  See "C++ Function Templates: How Do They Really Work?" on youtube.






                  share|improve this answer


























                    1












                    1








                    1







                    The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo) the compiler is unable to determine a type for T. And that's really the end of the story.



                    See Template argument deduction on C++ reference.



                    Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.



                    See "C++ Function Templates: How Do They Really Work?" on youtube.






                    share|improve this answer













                    The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo) the compiler is unable to determine a type for T. And that's really the end of the story.



                    See Template argument deduction on C++ reference.



                    Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.



                    See "C++ Function Templates: How Do They Really Work?" on youtube.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 21 '18 at 18:04









                    Peter RudermanPeter Ruderman

                    10.2k2352




                    10.2k2352























                        0














                        As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc and do an explicit cast. Consider the following code:



                        #include <vector>
                        #include <iostream>

                        template <typename T>
                        class A{
                        public:
                        A() { };
                        ~A() { };
                        // ...
                        template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
                        std::cout << "I am doing a conversion" << std::endl;
                        return std::vector<outT>(); }
                        };

                        template <typename T = float, typename... Args>
                        void myFunc(const std::vector<T, Args...>& _arg){
                        std::cout << "myFunc" << std::endl;
                        }

                        template <typename T>
                        void myFunc(const A<T>& _arg)
                        {
                        std::cout << "I am the second variant of myFunc" << std::endl;
                        myFunc(static_cast<const std::vector<T>>(_arg));
                        }

                        int main(int argc, char const *argv) {
                        A<int> foo;
                        std::cout << "-- First call of myFunc" << std::endl;
                        myFunc(foo);
                        std::cout << "-- Second call of myFunc" << std::endl;
                        std::vector<double> x = foo;
                        myFunc(x);

                        return 0;
                        }


                        Output of the program is:



                        -- First call of myFunc
                        I am the second variant of myFunc
                        I am doing a conversion
                        myFunc
                        -- Second call of myFunc
                        I am doing a conversion
                        myFunc


                        When you pass foo to myFunc the compiler uses the second overload of myFunc which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo to a std::vector, hence doing the conversion before passing the resulting std::vector to the first overload of myFunc. Notice that:




                        • you need a const conversion operator if you wnat to keep constness in the overloads of myFunc.


                        • you need an additional template parameter pack typename... Args in the first overload of myFunc to capture every specialization of std::vector (say, with a custom allocator).



                        Another option could be to declare A as class derived from std::vector. Something like the following code:



                        #include <vector>
                        #include <iostream>

                        template <typename T>
                        class A : public std::vector<T> {
                        public:
                        A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
                        };

                        template <typename T = float, typename... Args>
                        void myFunc(const std::vector<T, Args...>& _arg){
                        std::cout << "myFunc" << std::endl;
                        }

                        int main(int argc, char const *argv) {
                        A<int> foo;
                        myFunc(foo);

                        return 0;
                        }


                        In this case you do not need a conversion and you call myFunc by slicing. A drawback to this approach is that you do the conversion to a std::vector in the constructor and, every time you modify A, you must keep the data of the base class std::vector up to date.






                        share|improve this answer




























                          0














                          As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc and do an explicit cast. Consider the following code:



                          #include <vector>
                          #include <iostream>

                          template <typename T>
                          class A{
                          public:
                          A() { };
                          ~A() { };
                          // ...
                          template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
                          std::cout << "I am doing a conversion" << std::endl;
                          return std::vector<outT>(); }
                          };

                          template <typename T = float, typename... Args>
                          void myFunc(const std::vector<T, Args...>& _arg){
                          std::cout << "myFunc" << std::endl;
                          }

                          template <typename T>
                          void myFunc(const A<T>& _arg)
                          {
                          std::cout << "I am the second variant of myFunc" << std::endl;
                          myFunc(static_cast<const std::vector<T>>(_arg));
                          }

                          int main(int argc, char const *argv) {
                          A<int> foo;
                          std::cout << "-- First call of myFunc" << std::endl;
                          myFunc(foo);
                          std::cout << "-- Second call of myFunc" << std::endl;
                          std::vector<double> x = foo;
                          myFunc(x);

                          return 0;
                          }


                          Output of the program is:



                          -- First call of myFunc
                          I am the second variant of myFunc
                          I am doing a conversion
                          myFunc
                          -- Second call of myFunc
                          I am doing a conversion
                          myFunc


                          When you pass foo to myFunc the compiler uses the second overload of myFunc which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo to a std::vector, hence doing the conversion before passing the resulting std::vector to the first overload of myFunc. Notice that:




                          • you need a const conversion operator if you wnat to keep constness in the overloads of myFunc.


                          • you need an additional template parameter pack typename... Args in the first overload of myFunc to capture every specialization of std::vector (say, with a custom allocator).



                          Another option could be to declare A as class derived from std::vector. Something like the following code:



                          #include <vector>
                          #include <iostream>

                          template <typename T>
                          class A : public std::vector<T> {
                          public:
                          A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
                          };

                          template <typename T = float, typename... Args>
                          void myFunc(const std::vector<T, Args...>& _arg){
                          std::cout << "myFunc" << std::endl;
                          }

                          int main(int argc, char const *argv) {
                          A<int> foo;
                          myFunc(foo);

                          return 0;
                          }


                          In this case you do not need a conversion and you call myFunc by slicing. A drawback to this approach is that you do the conversion to a std::vector in the constructor and, every time you modify A, you must keep the data of the base class std::vector up to date.






                          share|improve this answer


























                            0












                            0








                            0







                            As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc and do an explicit cast. Consider the following code:



                            #include <vector>
                            #include <iostream>

                            template <typename T>
                            class A{
                            public:
                            A() { };
                            ~A() { };
                            // ...
                            template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
                            std::cout << "I am doing a conversion" << std::endl;
                            return std::vector<outT>(); }
                            };

                            template <typename T = float, typename... Args>
                            void myFunc(const std::vector<T, Args...>& _arg){
                            std::cout << "myFunc" << std::endl;
                            }

                            template <typename T>
                            void myFunc(const A<T>& _arg)
                            {
                            std::cout << "I am the second variant of myFunc" << std::endl;
                            myFunc(static_cast<const std::vector<T>>(_arg));
                            }

                            int main(int argc, char const *argv) {
                            A<int> foo;
                            std::cout << "-- First call of myFunc" << std::endl;
                            myFunc(foo);
                            std::cout << "-- Second call of myFunc" << std::endl;
                            std::vector<double> x = foo;
                            myFunc(x);

                            return 0;
                            }


                            Output of the program is:



                            -- First call of myFunc
                            I am the second variant of myFunc
                            I am doing a conversion
                            myFunc
                            -- Second call of myFunc
                            I am doing a conversion
                            myFunc


                            When you pass foo to myFunc the compiler uses the second overload of myFunc which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo to a std::vector, hence doing the conversion before passing the resulting std::vector to the first overload of myFunc. Notice that:




                            • you need a const conversion operator if you wnat to keep constness in the overloads of myFunc.


                            • you need an additional template parameter pack typename... Args in the first overload of myFunc to capture every specialization of std::vector (say, with a custom allocator).



                            Another option could be to declare A as class derived from std::vector. Something like the following code:



                            #include <vector>
                            #include <iostream>

                            template <typename T>
                            class A : public std::vector<T> {
                            public:
                            A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
                            };

                            template <typename T = float, typename... Args>
                            void myFunc(const std::vector<T, Args...>& _arg){
                            std::cout << "myFunc" << std::endl;
                            }

                            int main(int argc, char const *argv) {
                            A<int> foo;
                            myFunc(foo);

                            return 0;
                            }


                            In this case you do not need a conversion and you call myFunc by slicing. A drawback to this approach is that you do the conversion to a std::vector in the constructor and, every time you modify A, you must keep the data of the base class std::vector up to date.






                            share|improve this answer













                            As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc and do an explicit cast. Consider the following code:



                            #include <vector>
                            #include <iostream>

                            template <typename T>
                            class A{
                            public:
                            A() { };
                            ~A() { };
                            // ...
                            template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
                            std::cout << "I am doing a conversion" << std::endl;
                            return std::vector<outT>(); }
                            };

                            template <typename T = float, typename... Args>
                            void myFunc(const std::vector<T, Args...>& _arg){
                            std::cout << "myFunc" << std::endl;
                            }

                            template <typename T>
                            void myFunc(const A<T>& _arg)
                            {
                            std::cout << "I am the second variant of myFunc" << std::endl;
                            myFunc(static_cast<const std::vector<T>>(_arg));
                            }

                            int main(int argc, char const *argv) {
                            A<int> foo;
                            std::cout << "-- First call of myFunc" << std::endl;
                            myFunc(foo);
                            std::cout << "-- Second call of myFunc" << std::endl;
                            std::vector<double> x = foo;
                            myFunc(x);

                            return 0;
                            }


                            Output of the program is:



                            -- First call of myFunc
                            I am the second variant of myFunc
                            I am doing a conversion
                            myFunc
                            -- Second call of myFunc
                            I am doing a conversion
                            myFunc


                            When you pass foo to myFunc the compiler uses the second overload of myFunc which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo to a std::vector, hence doing the conversion before passing the resulting std::vector to the first overload of myFunc. Notice that:




                            • you need a const conversion operator if you wnat to keep constness in the overloads of myFunc.


                            • you need an additional template parameter pack typename... Args in the first overload of myFunc to capture every specialization of std::vector (say, with a custom allocator).



                            Another option could be to declare A as class derived from std::vector. Something like the following code:



                            #include <vector>
                            #include <iostream>

                            template <typename T>
                            class A : public std::vector<T> {
                            public:
                            A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
                            };

                            template <typename T = float, typename... Args>
                            void myFunc(const std::vector<T, Args...>& _arg){
                            std::cout << "myFunc" << std::endl;
                            }

                            int main(int argc, char const *argv) {
                            A<int> foo;
                            myFunc(foo);

                            return 0;
                            }


                            In this case you do not need a conversion and you call myFunc by slicing. A drawback to this approach is that you do the conversion to a std::vector in the constructor and, every time you modify A, you must keep the data of the base class std::vector up to date.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 22 '18 at 9:21









                            francescofrancesco

                            9241214




                            9241214






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53417606%2fhow-to-implicitly-convert-class-template-object-when-passing-as-argument-to-func%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                Guess what letter conforming each word

                                Port of Spain

                                Run scheduled task as local user group (not BUILTIN)