Sam Cristall
Sam Cristall

Reputation: 4387

Work around for template specialization bug in VC++12?

I have some code written for Clang 3.2 that I'm trying to port to run in VC++12. Clang 3.2+ and GCC 4.8 have no problem with it, but VC++12 complains. Here's a minimal snippet that produces the issue:

template <int(*ptr)()>
class foo {};

template<int N>
int ReturnsN() { return N; }

template<int N>
class bar {
  typedef foo<ReturnsN<N>> fooN; 
};

Now I'm pretty sure this is a compiler bug (but please let me know if it isn't!) The error given is:

'specialization' : cannot convert from 'int (__cdecl *)(void)' to 'int (__cdecl *)(void)'

So does anyone know a decent work around? It appears the compiler is convinced that the specialized function isn't completely defined.

EDIT: I should also note I've tried this with both the stock compiler, and the November 2013 CTP. Both have the same problem.

Upvotes: 4

Views: 192

Answers (3)

Constructor
Constructor

Reputation: 7483

Another possible workaround is to make ReturnsN function static member function of a class template:

template <int(*)()>
class foo;

template <int N>
struct Wrapper {
    static int ReturnsN() { return N; }
};

template <int N>
class bar {
    typedef foo<Wrapper<N>::ReturnsN> fooN; 
};

This code compiles fine with VC++ 2013.

Upvotes: 0

Sam Cristall
Sam Cristall

Reputation: 4387

In case anyone is curious, I found a workaround that's a little ugly. Basically just need to add a static member function to obscure the function, so it doesn't try to resolve the function specialization while also resolving the function pointer template parameter:

template <int(*ptr)()>
class foo {};

template<int N>
int ReturnsN() { return N; }

template<int N>
class bar {
private:
  static int Hack() {
    return ReturnsN<N>();
  }
public:
  typedef foo<Hack> fooN;
};

This compiles in all of VS2012, VS2013 and VS2013 November CTP.

Upvotes: 3

galop1n
galop1n

Reputation: 8824

A sad workaround and i suggest you submit a bug report to connect :

template < int (*)() >
class foo {};

template<int N>
int ReturnsN( ) { return N; }

template<int N>
class bar {
    static int myReturnsN() { return ReturnsN<N>; }
    using fooN = foo< myReturnsN >;
};

Upvotes: 3

Related Questions