Thread: compiler not inferring template type as expected

  1. #1
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445

    compiler not inferring template type as expected

    I'm using G++ 4.2.1 on linux 2.6.x, and I am trying to get the compiler to automatically know what type I want a template to use based on the lvalue of an assignment like the following:
    Code:
    template<class T>
    T myfunc(double d)
    {
      return (T)d;
    }
    
    int i;
    i = myfunc(1.0);
    is this legal c++ code? or do I have to explicitly say:
    Code:
    i = myfunc<int>(1.0);

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The compiler can impossibly deduce what type your function is going to return, so you must specify it explicitly, like you have done in your example.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    that's sort of counter-intuitive to me, since the compiler knows exactly what type 'i' is, and I would think that it should be able to figure that out.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Ah yes, well no.
    What if it returns some class that can implicitly convert to int?
    C++ is not easy language to parse.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Elkvis View Post
    that's sort of counter-intuitive to me, since the compiler knows exactly what type 'i' is, and I would think that it should be able to figure that out.
    Why should the compiler assume that there is no conversion in the assignment? At any rate the return type of a function is not a part of its signature.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    do you know if C++0x will add return type to the signature of a function?

    if I could overload functions with only the return types being different, this would not be an issue, but because C++ doesn't allow it, I have to resort to all this template trickery.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Not my knowledge, no.
    I believe you have flawed design.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    you have to admit that there would be plenty of things which would be easier if it were possible to do what I suggest.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Perhaps. Perhaps not.
    The best you can do is outline your design and help others punch a hole in it and suggest corrections.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I don't think the design is necessarily flawed, just that you have to be explicit about the return type. What if the return type was not assigned to a variable, but used differently:

    Code:
    std::cout << myfync(1.0); //what would T be
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    There already is one instance where the C++ compiler determines something by the target type: taking the address of an overloaded function:
    Code:
    void f(int);
    void f(double);
    
    int main()
    {
      void (*fp1)(int) = &f; // Takes the address of void f(int)
      void (*fp2)(double) = &f; // Takes the address of void f(double)
      void (*fp3)(void*) = &f; // Error: no appropriate overload
      std::cout << &f; // Error: cannot deduce overload
    }
    However, to extend this to templates would require making the return type part of the function signature. This, in turn, would break ABI (name mangling rules would have to change), something the new standard really tries to avoid.

    Edit: Hmm, wait, it wouldn't require the signature change. Ah, well, I guess I have no idea why they didn't do this. It would allow for some sweet code, but its absence is not crippling.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #12
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    I'll go into a bit of detail about what I am trying to do.

    I have a class that accepts a string (similar in format to an HTTP post string), and splits it up into its key/value pairs. The accessor function for these pairs is declared as follows:
    Code:
    std::string GetKeyValue(const std::string& str):
    sometimes I want to get a key as an integer because it contains a numeric value, so it would be nice to have an overload of the function that returns int, but takes the same parameters.

    my solution was the following:
    Code:
    template <class T> T _GetKeyValue(const std::string& str)
    {
      T t;
      GKV(str, t);
      return t;
    }
    
    void GKV(const string& str, std::string& t);
    void GKV(const string& str, int& t);
    void GKV(const string& str, double& t);
    void GKV(const string& str, long& t);
    I could then just add another overload for any new type I want to return, but as you can tell from this thread, this didn't work as expected.

  13. #13
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    True. That's why, for example, you have to specify the return type in boost::lexical_cast:
    Code:
    template <typename Out, typename In>
    Out lexical_cast(const In& in)
    {
    ...
    }
    
    int i = lexical_cast<int>("224");
    Of course, the authors don't mind, because other casts look like this, too.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  14. #14
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    You can, if you want, write a user level function in terms of a return template proxy in order to facilitate overloading the behavior of a function based solely on the target return type.

    I pulled this out of my headers and patched things up to remove other dependencies. This simple mechanic should handle about 90% of uses without problems. (The most obvious case of conversion problems relating to using an instance of the proxy class with the C++ operators, as is normally a concern for conversion operators, should never arise with a conformant compiler simply because the relevant operator is a template, but it is actually possible to trick the compiler, but it should not come up naturally.) With the right utilities you can handle the rest and provide better errors. (As it stands, the errors a good compiler will produce will make you cry.)

    Soma

    Code:
    #include <iostream>
    #include <sstream>
    #include <string>
    
    template
    <
       typename function_F
    >
    struct return_mastery
    {
       return_mastery
       (
          const std::string & data_f
       ):
         data_m(data_f)
       {
       }
       template
       <
          typename type_F
       >
       inline operator type_F ()
       {
          typedef typename function_F::template apply<type_F>::type function_type;
          function_type converter;
          return(converter(data_m));
       }
       std::string data_m;
    };
    
    template
    <
       typename type_F
    >
    struct sample_function
    {
       template
       <
          typename type_FR
       >
       struct apply
       {
          typedef sample_function<type_FR> type;
       };
       inline type_F operator ()
       (
          const std::string & data_f
       )
       {
          type_F return_value;
          std::istringstream in(data_f);
          std::cout << typeid(type_F).name() << ": ";
          in >> return_value;
          return(return_value);
       }
       typedef sample_function<type_F> type;
    };
    
    template <> struct sample_function<double>
    {
       template
       <
          typename type_FR
       >
       struct apply
       {
          typedef sample_function<type_FR> type;
       };
       inline double operator ()
       (
          const std::string & data_f
       )
       {
          double return_value;
          std::istringstream in(data_f);
          std::cout << "This is for a double: ";
          in >> return_value;
          return(return_value);
       }
       typedef sample_function<double> type;
    };
    
    inline return_mastery<sample_function<void>::type> tester
    (
       const std::string & data_f
    )
    {
       return(return_mastery<sample_function<void>::type>(data_f));
    }
    
    int main()
    {
       char c(tester("!")); std::cout << c << '\n';
       signed char sc(tester("@")); std::cout << sc << '\n';
       unsigned char uc(tester("$")); std::cout << uc << '\n';
       short s(tester("18")); std::cout << s << '\n';
       signed short ss(tester("-400")); std::cout << ss << '\n';
       unsigned short us(tester("63000")); std::cout << us << '\n';
       int i(tester("78411")); std::cout << i << '\n';
       signed int si(tester("-1145989")); std::cout << si << '\n';
       unsigned int ui(tester("2482918294")); std::cout << ui << '\n';
       long l(tester("95438")); std::cout << l << '\n';
       signed long sl(tester("-72984529")); std::cout << sl << '\n';
       unsigned long ul(tester("31821938")); std::cout << ul << '\n';
       float f(tester("14.178")); std::cout << f << '\n';
       double d(tester("2091.0817")); std::cout << d << '\n';
       return(0);
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 0
    Last Post: 03-20-2008, 07:59 AM
  2. ras.h errors
    By Trent_Easton in forum Windows Programming
    Replies: 8
    Last Post: 07-15-2005, 10:52 PM
  3. Windows using Dev-C++
    By Renegade in forum C++ Programming
    Replies: 15
    Last Post: 07-07-2005, 08:29 PM
  4. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  5. Erros in Utility Header File
    By silk.odyssey in forum C++ Programming
    Replies: 4
    Last Post: 12-22-2003, 06:17 AM