unable to resolve template parameter

Discussion in 'C++' started by Noah Roberts, Dec 2, 2009.

  1. Noah Roberts

    Noah Roberts Guest

    What is wrong with the following code because I just can't see it:

    #include <string>
    #include <iostream>

    namespace something {

    template < typename R, typename T >
    inline R f(T const& x)
    {
    return R(x);
    }
    }

    template < typename T >
    struct test
    {
    test(double d = something::f<double>(5))
    : test_double(d) {}

    double test_double;
    };

    int main()
    {
    test<int> t;

    std::cout << t.test_double;

    std::cin.get();
    }

    The compiler complains that it cannot resolve R in the call to
    something::f<double>() in the test constructor. It only happens in
    default arguments and only if you need namespace resolution to get to f
    <>.

    If the line "test(double d = something::f<double>(5))" is changed to
    "test(double d = f<double>(5))" and a "using namespace something" is
    placed above the structure declaration, the code compiles just fine.

    Here's the actual compiler error:

    1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(17) : error
    C2783: 'R something::f(const T &)' : could not deduce template argument
    for 'R'
    1> d:\dev_workspace\experimental\scratch\scratch\main.cpp(7) :
    see declaration of 'something::f'

    This makes no sense to me at all. Am I running into some obscure C++
    standard thing or is this compiler just broken?

    This was actually discovered in an attempt to provide a string default
    argument through a boost::lexical_cast.
    Noah Roberts, Dec 2, 2009
    #1
    1. Advertising

  2. On Dec 2, 7:02 pm, Noah Roberts <> wrote:
    > What is wrong with the following code because I just can't see it:
    >
    > #include <string>
    > #include <iostream>
    >
    > namespace something {
    >
    >   template < typename R, typename T >
    >   inline R f(T const& x)
    >   {
    >     return R(x);
    >   }
    >
    > }
    >
    > template < typename T >
    > struct test
    > {
    >   test(double d = something::f<double>(5))
    >     : test_double(d) {}
    >
    >   double test_double;
    >
    > };
    >
    > int main()
    > {
    >   test<int> t;
    >
    >   std::cout << t.test_double;
    >
    >   std::cin.get();
    >
    > }
    >
    > The compiler complains that it cannot resolve R in the call to
    > something::f<double>() in the test constructor.


    Comeau C++ compiles it so it is probably a compiler bug.
    Gert-Jan de Vos, Dec 2, 2009
    #2
    1. Advertising

  3. Noah Roberts

    luther13 Guest

    As f() is a template of 2 typename,
    you must call:
    something::f<typename R,double>(5)


    "Gert-Jan de Vos" <> a écrit dans le
    message de news:
    ...
    On Dec 2, 7:02 pm, Noah Roberts <> wrote:
    > What is wrong with the following code because I just can't see it:
    >
    > #include <string>
    > #include <iostream>
    >
    > namespace something {
    >
    > template < typename R, typename T >
    > inline R f(T const& x)
    > {
    > return R(x);
    > }
    >
    > }
    >
    > template < typename T >
    > struct test
    > {
    > test(double d = something::f<double>(5))
    > : test_double(d) {}
    >
    > double test_double;
    >
    > };
    >
    > int main()
    > {
    > test<int> t;
    >
    > std::cout << t.test_double;
    >
    > std::cin.get();
    >
    > }
    >
    > The compiler complains that it cannot resolve R in the call to
    > something::f<double>() in the test constructor.


    Comeau C++ compiles it so it is probably a compiler bug.
    luther13, Dec 2, 2009
    #3
  4. Noah Roberts

    Noah Roberts Guest

    In article <4b16d670$0$24769$>,
    says...
    >
    > As f() is a template of 2 typename,
    > you must call:
    > something::f<typename R,double>(5)


    I think you've misunderstood. The 'double' parameter supplied is not
    meant to say what the function argument type is, that is meant to be
    resolved by the compiler. The return type 'R' is what is being supplied
    and it's being supplied at the call site, like it should be. This is
    valid in C++, so long as your supplied types come before your resolved
    types in the parameter list, and usually works just fine.

    As I expected, the compiler doesn't even think what you've provided is
    syntatically valid:


    1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(17) : error
    C2146: syntax error : missing ',' before identifier 'R'
    1> d:\dev_workspace\experimental\scratch\scratch\main.cpp(21) :
    see reference to class template instantiation 'test<T>' being compiled
    1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(17) : error
    C2065: 'R' : undeclared identifier
    1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(17) : error
    C2146: syntax error : missing ',' before identifier 'R'
    1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(17) : error
    C2146: syntax error : missing ',' before identifier 'R'
    1> d:\dev_workspace\experimental\scratch\scratch\main.cpp(25) :
    see reference to class template instantiation 'test<T>' being compiled
    1> with
    1> [
    1> T=int
    1> ]
    1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(17) : error
    C2146: syntax error : missing ',' before identifier 'R'
    1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(17) : error
    C2783: 'R something::f(const T &)' : could not deduce template argument
    for 'R'
    1> d:\dev_workspace\experimental\scratch\scratch\main.cpp(7) :
    see declaration of 'something::f'

    There's no syntatically valid way to specify that you want the compiler
    to resolve a template parameter that comes before one you're explicitly
    supplying.

    Explicitly providing the argument type parameter at the call site
    doesn't cause the original problem to go away either. As in changing
    the test constructor to "test(double d = something::f<double, int>(5))"
    still causes a compiler complaint about R being unresolvable.
    Noah Roberts, Dec 2, 2009
    #4
  5. Noah Roberts

    Noah Roberts Guest

    In article <597a2b29-13b0-4eea-bd9b-9d7ad6836284
    @b2g2000yqi.googlegroups.com>,
    says...
    >
    > On Dec 2, 7:02 pm, Noah Roberts <> wrote:
    > > What is wrong with the following code because I just can't see it:
    > >
    > > #include <string>
    > > #include <iostream>
    > >
    > > namespace something {
    > >
    > >   template < typename R, typename T >
    > >   inline R f(T const& x)
    > >   {
    > >     return R(x);
    > >   }
    > >
    > > }
    > >
    > > template < typename T >
    > > struct test
    > > {
    > >   test(double d = something::f<double>(5))
    > >     : test_double(d) {}
    > >
    > >   double test_double;
    > >
    > > };
    > >
    > > int main()
    > > {
    > >   test<int> t;
    > >
    > >   std::cout << t.test_double;
    > >
    > >   std::cin.get();
    > >
    > > }
    > >
    > > The compiler complains that it cannot resolve R in the call to
    > > something::f<double>() in the test constructor.

    >
    > Comeau C++ compiles it so it is probably a compiler bug.


    That's really where I'm leaning too. It's just such a basic, everyday
    use that I'm pretty blown away that it made it through QA. I guess
    that's just MS for you though.
    Noah Roberts, Dec 2, 2009
    #5
  6. Noah Roberts

    James Kanze Guest

    On Dec 2, 10:28 pm, Noah Roberts <> wrote:
    > In article <597a2b29-13b0-4eea-bd9b-9d7ad6836284
    > @b2g2000yqi.googlegroups.com>,
    > says...
    > > On Dec 2, 7:02 pm, Noah Roberts <> wrote:
    > > > What is wrong with the following code because I just can't
    > > > see it:


    > > > #include <string>
    > > > #include <iostream>


    > > > namespace something {


    > > > template < typename R, typename T >
    > > > inline R f(T const& x)
    > > > {
    > > > return R(x);
    > > > }
    > > > }


    > > > template < typename T >
    > > > struct test
    > > > {
    > > > test(double d = something::f<double>(5))
    > > > : test_double(d) {}


    > > > double test_double;


    > > > };


    > > > int main()
    > > > {
    > > > test<int> t;


    > > > std::cout << t.test_double;


    > > > std::cin.get();
    > > > }


    > > > The compiler complains that it cannot resolve R in the
    > > > call to something::f<double>() in the test constructor.


    > > Comeau C++ compiles it so it is probably a compiler bug.


    G++ does as well, and I can't think of anything in the standard
    which would make this a special case.

    > That's really where I'm leaning too. It's just such a basic,
    > everyday use that I'm pretty blown away that it made it
    > through QA. I guess that's just MS for you though.


    IIRC, you said that it only occurs in default arguments, and
    only if there is a namespace qualifier. Which means that it is
    a result of some faulty interaction between different features.
    Off hand, it makes me wonder about the design of the compiler
    (no encapsulation?), but it doesn't surprise me too much that it
    slipped through quality control: given the number of features of
    C++, you can't really test all possible combinations.

    --
    James Kanze
    James Kanze, Dec 3, 2009
    #6
  7. Noah Roberts

    Triple-DES Guest

    On 2 Des, 19:02, Noah Roberts <> wrote:
    > What is wrong with the following code because I just can't see it:


    [...]

    > Here's the actual compiler error:
    >
    > 1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(17) : error
    > C2783: 'R something::f(const T &)' : could not deduce template argument
    > for 'R'
    > 1>        d:\dev_workspace\experimental\scratch\scratch\main.cpp(7) :
    > see declaration of 'something::f'
    >
    > This makes no sense to me at all.  Am I running into some obscure C++
    > standard thing or is this compiler just broken?
    >
    > This was actually discovered in an attempt to provide a string default
    > argument through a boost::lexical_cast.


    I reproduced the same issue with the following code:

    namespace ns { template<typename T> T f(); }
    struct C { C( int i = ns::f<int>() ); }; // C2783
    int main() {}

    Clearly the diagnostic is erroneous since there shouldn't be any
    template argument deduction for this program. I have reported it to
    Microsoft here:
    http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=518117#details
    Triple-DES, Dec 8, 2009
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    1
    Views:
    10,109
  2. Stuart Redmann
    Replies:
    5
    Views:
    468
    Stuart Redmann
    Dec 14, 2007
  3. sunil
    Replies:
    8
    Views:
    382
    sunil
    Jun 20, 2008
  4. Replies:
    2
    Views:
    998
  5. John K
    Replies:
    4
    Views:
    518
    Walter Wang [MSFT]
    Oct 27, 2006
Loading...

Share This Page