Я конвертирую существующий класс, который имеет набор функций-членов шаблона, специализирующихся на значениях перечислителя в классе, в класс шаблона. Однако язык не позволяет специализовать функции-члены шаблона без специализации шаблона класса, поэтому это не работает:
template <typename x_Dummy>
class t_Test
{
public:
enum t_KindId{first, second};
public:
template <t_KindId x_kind> auto doo() -> void;
};
template <typename x_Dummy>
template<>
inline auto t_Test<x_Dummy>::doo<t_Test<x_Dummy>::t_KindId::first>() -> void
{
return;
}
Итак, я понял, что могу обойти эту проблему, поместив тело функции шаблона внутри статической функции частичной специализации в классе внутреннего класса шаблона. Однако этот подход также не работает:
template <typename x_Dummy>
class t_Test
{
public:
enum class t_KindId{first, second};
public:
template <t_KindId x_kind> auto doo() -> void;
private:
template <t_KindId x_kind, typename xx_Dummy = void>
class t_DooImpl;
private:
template <typename xx_Dummy>
class t_DooImpl<t_KindId::first, xx_Dummy> final
{
friend auto t_Test<x_Dummy>::doo<t_KindId::first>() -> void;
private:
static inline auto doo_impl([[maybe_unused]] t_Test<x_Dummy> & self) -> void
{
return;
}
};
};
template <typename x_Dummy>
template <typename t_Test<x_Dummy>::t_KindId x_kind>
inline auto t_Test<x_Dummy>::doo(void) -> void
{
return t_DooImpl<x_kind>::doo_impl(*this);
}
int main()
{
using t_Test = t_Test<int>;
t_Test t{};
t.doo<t_Test::t_KindId::first>();
return 0;
}
Clang дает :
prog.cc:30:9: error: no candidate function template was found for dependent friend function template specialization
doo<t_KindId::first>(void) -> void;
^
prog.cc:52:26: error: incomplete definition of type 't_Test<int>::t_DooImpl<t_Test<int>::t_KindId::first, void>'
return t_DooImpl<x_kind>::doo_impl(*this);
~~~~~~~~~~~~~~~~~^~
prog.cc:59:4: note: in instantiation of function template specialization 't_Test<int>::doo<t_Test<int>::t_KindId::first>' requested here
t.doo<t_Test::t_KindId::first>();
^
2 errors generated.
gcc дает :
prog.cc: In instantiation of 'class t_Test<int>::t_DooImpl<(t_Test<int>::t_KindId)0, void>':
prog.cc:52:36: required from 'void t_Test<x_Dummy>::doo() [with t_Test<x_Dummy>::t_KindId x_kind = (t_Test<int>::t_KindId)0; x_Dummy = int]'
prog.cc:59:33: required from here
prog.cc:29:15: error: 'doo' was not declared in this scope
friend auto t_Test<x_Dummy>::
^~~~~~~~~~~~~~~
prog.cc:29:15: note: suggested alternative: 'bool'
friend auto t_Test<x_Dummy>::
^~~~~~~~~~~~~~~
bool
prog.cc: In instantiation of 'void t_Test<x_Dummy>::doo() [with t_Test<x_Dummy>::t_KindId x_kind = (t_Test<int>::t_KindId)0; x_Dummy = int]':
prog.cc:59:33: required from here
prog.cc:52:36: error: 'static void t_Test<x_Dummy>::t_DooImpl<t_Test<x_Dummy>::t_KindId::first, xx_Dummy>::doo_impl(t_Test<x_Dummy>&) [with xx_Dummy = void; x_Dummy = int]' is private within this context
return t_DooImpl<x_kind>::doo_impl(*this);
~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
prog.cc:33:3: note: declared private here
doo_impl
^~~~~~~~
vc ++ дает:
warning C4348: 't_Test<int>::t_DooImpl': redefinition of default parameter: parameter 2
note: see declaration of 't_Test<int>::t_DooImpl'
note: see reference to class template instantiation 't_Test<int>' being compiled
error C2027: use of undefined type 't_Test<int>::t_DooImpl<t_Test<int>::t_KindId::first,void>'
note: see declaration of 't_Test<int>::t_DooImpl<t_Test<int>::t_KindId::first,void>'
note: see reference to function template instantiation 'void t_Test<int>::doo<t_Test<int>::t_KindId::first>(void)' being compiled
note: see reference to function template instantiation 'void t_Test<int>::doo<t_Test<int>::t_KindId::first>(void)' being compiled
error C3861: 'doo_impl': identifier not found
Я не уверен насчет синтаксиса здесь, но похоже, что проблема вызвана объявлением друга. Если я сделаю функцию doo_impl
общедоступной и удалим объявление friend
, то она прекрасно компилируется с clang и gcc, но vc все равно жалуется. Поэтому я ищу предложения о том, как это можно исправить или, возможно, для более простого обходного пути.