New question
edit
This bug seems to be the same as this one:
MSVC rejects the following code:
template <template <typename T, typename T::mytype x> class X>
struct z
{};
template <typename T, typename T::mytype xx>
struct x
{};
z<x> zz;
error C3201: the template parameter list for class template 'x' does not match the template parameter list for template parameter 'X'
But class template x has the same set of template parameters as parameter X does.
Hell! This bug report is from april 2012 ?!
With
Status: Closed as Deferred
:(
Microsoft, I am disappoint TT
edit of edit
In my case (below), I can hack my way to do what I want, but it's ugly:
//Library code
struct Boundary {
double sup, inf;
};
template <
class UserBoundaries,
template <size_t, bool...> class LocalInfo,
size_t hack>
struct Space_LocalParameters : LocalInfo<hack> {};
//User code
struct Boundaries_Problem7 {
Boundary b1, b2, b3;
};
template <size_t, bool...>
struct LocalInfo_Problem7 {};
template <size_t hack, bool... args>
struct Problem7_Functions
: Space_LocalParameters < Boundaries_Problem7, LocalInfo_Problem7, hack, args...> {};
int main() {}
Use:
//Compute the offset of member b2 in Boundaries_Problem7
const size_t hack = (size_t)(&((Boundaries_Problem7*)0)->b2);
if (...)
problem.functions[k].SetFunction(&Problem7_Functions<hack, true, false>::f);
else if (...)
problem.functions[k].SetFunction(&Problem7_Functions<hack, false, true>::f);
else problem.functions[k].SetFunction(&Problem7_Functions<hack, false, false>::f);
//Later in that function
if (boundary_Inf) {
value += this->points[0].coef
* ((Boundary*)((char*)&domain.boundaries + hack))->inf;
}
if (boundary_Sup) {
value += this->points[N-1].coef
* ((Boundary*)((char*)&domain.boundaries + hack))->sup;
}
Is the compiler allowed to change the offset of a member during optimization ?
end of edit
New question
The following compiles fine on http://coliru.stacked-crooked.com/a/be088e06861f9349
//Library code
struct Boundary {};
template <
class UserBoundaries,
template <Boundary UserBoundaries::*> class LocalInfo,
Boundary UserBoundaries::*m_ptr>
struct Space_LocalParameters : LocalInfo<m_ptr> {};
//User code
struct Boundaries_Problem7 {
Boundary b1, b2, b3;
};
template <Boundary Boundaries_Problem7::*m_ptr>
struct LocalInfo_Problem7 {};
template <Boundary Boundaries_Problem7::*ptr>
struct Problem7_Functions
: Space_LocalParameters < Boundaries_Problem7, LocalInfo_Problem7, ptr> {}; // <-- C3201
int main() {}
But visual studio 2013 gives me this error:
error C3201: the template parameter list for class template 'LocalInfo_Problem7' does not match the template parameter list for template parameter 'LocalInfo'
Is this a VS compiler bug ? Or is my code wrong ?
I wrote a bug report here https://connect.microsoft.com/VisualStudio/feedback/details/933984/c-visual-studio-2013-compiler-bug-template-template-pointer-to-member-issue
If this is a bug, how could I get this to work ?
Thanks for your help.
Old question
I have some troubles with a somewhat complex template "typedef".
Simplifying the problem as much as possible, I came up with this:
template <class A, template <A*> class B, A* ptr>
struct Foo : B<ptr> {};
template <class, class AA, template <AA*> class BB, AA* ptr>
using Bar = Foo<AA, BB, ptr>; // <-- C3201
visual studio 2013 gives me: error C3201: the template parameter list for class template 'BB' does not match the template parameter list for template parameter 'B'
I don't see what is wrong.
Foo<AA, BB, ptr>
"expands to" template <class AA, template <AA*> class BB, AA* ptr> struct Foo : BB<ptr> {}
In theory, if we define the follwing (I did not actually try to compile the following):
class MyClass {} myClass_instance;
template <MyClass*> class MyTemplateClass {};
Then
Bar<whatever, MyClass, MyTemplateClass, &myClass_instance>
should be an alias for
Foo<MyClass, MyTemplateClass, &myClass_instance> : MyTemplateClass<&myClass_instance>
This looks ok to me.
Curiously, the two following variations compile fine:
1/ Changing template <A*>
and template <AA*>
with template <Z*>
class Z;
template <class A, template <Z*> class B, A* ptr>
struct Foo : B<ptr> {};
template <class, class AA, template <Z*> class BB, AA* ptr>
using Bar = Foo<AA, BB, ptr>;
This workaround let my program run fine, but this defeat the purpose my template approach.
Or 2/ Removing the first template parameter of Bar
template <class A, template <A*> class B, A* ptr>
struct Foo : B<ptr> {};
template <class AA, template <AA*> class BB, AA* ptr>
using Bar = Foo<AA, BB, ptr>;
So what is the mismatch mentioned by the compiler?
How comes removing the first template parameter of Bar solves the problem ?
Thanks for your help.