Template function specialization with default template arguments within template class

I'm getting the following error on Visual Studio:
error C2783: 'R TestClass<char>::foo(void) const' : could not deduce template argument for 'R'

With this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
template<typename T>
class TestClass
{
public:
	template<typename R = unsigned int>
	R foo() const;
};

template<typename T>
template<typename R>
R TestClass<T>::foo() const
{
	return R(0);
}

template<>
template<typename R>
R inline TestClass<char>::foo() const
{
	return R(1);
}

template<>
template<typename R>
R inline TestClass<wchar_t>::foo() const
{
	return R(2);
}

int main()
{
	TestClass<char> testClass;
	testClass.foo();
	return 0;
}


Is there anything I can do to deduce the type specified on line 5 without modifying line 33, or would I have to define another template function outside of the class? This error only occurs when the function is specialized.

edit: This seems to work, but is there a way without defining another function?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
template<typename T>
class TestClass
{
public:
	template<typename R = unsigned int>
	R foo() const;

private:
	template<typename R>
	R fooHelper() const;
};

template<typename T>
template<typename R>
R TestClass<T>::foo() const
{
	return this->fooHelper<R>();
}

template<typename T>
template<typename R>
R TestClass<T>::fooHelper() const
{
	return R(0);
}

template<>
template<typename R>
R inline TestClass<char>::fooHelper() const
{
	return R(1);
}

template<>
template<typename R>
R inline TestClass<wchar_t>::fooHelper() const
{
	return R(2);
}

int main()
{
	TestClass<char> testClass;
	testClass.foo();
	return 0;
}
Last edited on
If you're writing a function template, prefer to write it as a single function template that should never be specialized or overloaded, and implement the function template entirely in terms of a class template. This is the proverbial level of indirection that steers you well clear of the limitations and dark corners of function templates. This way, programmers using your template will be able to partially specialize and explicitly specialize the class template to their heart's content without affecting the expected operation of the function template. This avoids both the limitation that function templates can't be partially specialized, and the sometimes surprising effect that function template specializations don't overload.
- Sutter http://www.gotw.ca/publications/mill17.htm


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

template < typename T > struct test
{
    template < typename R = T, typename U = T, typename = void > struct bar { static constexpr R value = 0 ; };
    template < typename R, typename VOID > struct bar<R,char,VOID> { static constexpr R value = 1 ; };
    template < typename R, typename VOID > struct bar<R,wchar_t,VOID> { static constexpr R value = 2 ; };

    template < typename R = unsigned int > constexpr R foo() const { return bar<R,T>::value ; }
};

int main()
{
    test<int> i ;
    std::cout << i.foo() << '\n' ; // 0

    test<char> c ;
    std::cout << c.foo() << '\n' ; // 1

    test<wchar_t> w ;
    std::cout << w.foo() << '\n' ; // 2
}

http://coliru.stacked-crooked.com/a/7cf85a7f6d583bb5
Topic archived. No new replies allowed.