I've
been trying to use conceptgcc-BoostCon on Linux/x86 to write a concept
map template to apply to types that derive from a base template class,
but not having much luck...
Consider this code:
#include <concepts>
concept C<typename T> {}
template<typename T>
struct Base {};
// template concept map to apply to any type that is derived from
Base<T>
template<typename T, std::DerivedFrom<Base<T>>
TDerived>
concept_map C<TDerived> {}
struct Derived : public Base<char> {};
template<C T>
void Foo(T t) {}
int main() {
Derived d;
Foo(d);
return 0;
}
Compiling this results in the following error:
file.cpp:10: error: template parameters not used in
partial specialization:
file.cpp:10: error: `T'
file.cpp: In function `int main()':
file.cpp:19: no matching function for call to `Foo(Derived&)'
file.cpp:15: note: candidates are: void Foo(T) [with T = Derived]
<where clause>
file.cpp:19: note: no concept map for requirement `C<Derived>'
file.cpp:3: note: concept `C<Derived>' syntactically matches
file.cpp:19: note: if the concept semantics are met, write a concept
map:
concept_map C<Derived> {};
I have been unable to identify any section in n2193 that specifies that
all template parameters must be referenced within the concept-id
concept_map is mapping. It seems to me that use of all template
parameters by a combination of the requires clause and concept-id
should be supportable, so I'm not sure if this is an unimplemented
feature in conceptgcc, a bug, a design/specification issue, or a
misunderstanding on my part.
I've tried working around the unused template parameter issue by using
another class to perform the lookup.
template<typename T,
std::DerivedFrom<Base<T>> TDerived>
struct MyDerivedFrom {
typedef TDerived type;
};
template<typename T, typename TDerived>
concept_map C<typename MyDerivedFrom<T, TDerived>::type> {}
This does avoid the unused template parameters error, however the code
still fails to compile.
file.cpp: In function `int main()':
file.cpp:23: no matching function for call to `Foo(Derived&)'
file.cpp:19: note: candidates are: void Foo(T) [with T = Derived]
<where clause>
file.cpp:23: note: no concept map for requirement `C<Derived>'
file.cpp:3: note: concept `C<Derived>' syntactically matches
file.cpp:23: note: if the concept semantics are met, write a concept
map:
concept_map C<Derived> {};
For my own code, I was able to work around this by forcing the template
base class to derive from a non-template base class and then declare
the concept_map to apply to any type that derives from the non-template
base class.
struct Base {};
template<typename T>
struct TemplateBase : public Base {};
template<std::DerivedFrom<Base> T>
concept_map C<T> {}
Tom.