2

I want to use a default argument that is initialized with a static member function. I have the following example :

//A.h
#include <string>
class A
{
 public:
   template<class T>
   static T& Get(const std::wstring&);
};

//Util.h
#include "A.h"
#include <string>

class B
{
 public:
  void f(
    double d,
    double c = A::Get<double>(L"test"));
}

//main.cpp
#include "Util.h"
int main()
{
    B b;
    b.f(5);
}

The error I am getting is

util.h(7): error C2783: 'T &A::Get(const std::wstring &)' : could not deduce template argument for 'T'.

I can't get why this does not compile.

EDIT: I am using visual studio 2010 sp1. And it seem this is compiler bug. If I change Get to be global and not static member of A, it compiles.

user152508
  • 2,971
  • 8
  • 34
  • 56

2 Answers2

4

There is nothing in the function template's signature that allows the compiler to deduce the template type, so you need to be explicit. Your default argument for function f should be:

double c = A::Get<double>(L"test")

Compiler can not deduce the template argument by looking at what variable type is return value assigned to.


template <typename T>
T fn1(int a); // Can not deduce template type

template <typename T>
T fn2(T b); // It is possible to deduce template type from function arguments
Mohit Jain
  • 29,414
  • 8
  • 65
  • 93
  • he is using class T not typename T – Irrational Person Jan 14 '15 at 07:45
  • 3
    @IrrationalPerson So what? They're strictly 100% equivalent. – Angew is no longer proud of SO Jan 14 '15 at 07:49
  • Ok I just realized that the code sample I post is not same with my real situation. So I edited the code. Please see the edited code. The proposed solution works if f is global, but not if it is member of class.So I still get the compiler error can not deduce template argument for T, although I am calling Get – user152508 Jan 14 '15 at 08:00
  • 2
    @user152508 [Works for me](http://ideone.com/wYfUPZ) (the errors in the link are link-time errors, compilation has succeeded). Can you post something which really reproduces the error you're getting? – Angew is no longer proud of SO Jan 14 '15 at 08:11
  • I am using visual studio 2010 sp1. It doesnot work for me. I now it is strange. I am testing with this 2 days with no lack. Can't get it why it does not work, it gives me the same error can't deduce template argument. Can this be bug in the compiler – user152508 Jan 14 '15 at 08:17
  • Strange thing is if I make Get global function instead of static member of A, it works – user152508 Jan 14 '15 at 08:19
  • @user152508 What happens 1. If you replace `class A` with `namespace A`. 2. If you change argument of `f` from `const std::wstring&` to `const wchar *`? – Mohit Jain Jan 14 '15 at 08:27
  • @user152508 In VS2010, I am getting the same error you are. You should add the fact that you're using VS2010 to your question. – Angew is no longer proud of SO Jan 14 '15 at 08:32
  • @Mohit Jain , I did both things, still same. I will add to my question that I am using visual studio 2010 sp1 – user152508 Jan 14 '15 at 08:38
  • @Angew, `They're strictly 100% equivalent.`. Though you are saying is mostly correct, but [`class` and `tempalte` are not 100% interchangeable](http://stackoverflow.com/a/2024173/514235). Besides the link, there is 1 more corner case where `typename` cannot be replaced with `class`. It is somewhere in SO, but unable to find that. :-) – iammilind Jan 14 '15 at 08:45
  • @IrrationalPerson Of course `class` and `typename` are not 100% interchangeable in every context (`typename A { int x; }` is nonsense), but when declaring a template type parameter, they're total synonyms. – Angew is no longer proud of SO Jan 14 '15 at 08:50
0

You've mentioned you're using VS2010. With this, I get the same error you do, even though the code is perfectly legal and should compile (which it does with gcc, for example). So it's a compiler bug. I worked around it by including a global wrapper for the static member function:

template <class T>
T& GlobalGet(const std::wstring& x)
{
  return A::Get<T>(x);
}

class B
{
 public:
  void f(
    double d,
    double c = GlobalGet<double>(L"test"));
};
Angew is no longer proud of SO
  • 156,801
  • 13
  • 318
  • 412