std :: enable_if для метода шаблона, определенного в cpp - PullRequest
0 голосов
/ 03 февраля 2020

Я работаю над шаблонным классом, определения методов которого находятся в файле cpp. Теперь я хотел бы добавить другой метод, который будет включен только для определенного параметра шаблона класса. Мой текущий подход:

.h

template <typename T>
class MyClass
{
   template <typename U = T,
             typename std::enable_if<std::is_same<SpecialType, U>::value>::type* = 0>
   T& Foo();
}

. cpp

template <typename T>
template <typename U,
          typename std::enable_if<std::is_same<SpecialType, U>::value>::type*>
T& MyClass<T>::Foo()
{
   // Implementation...
}

// Exported explicit instantiations
template class __declspec(dllexport) MyClass<SpecialType>;
template class __declspec(dllexport) MyClass<OtherType>;
...

Это прекрасно компилируется как в реализации cpp, так и на сайтах, которые включают заголовок. Проблема с компоновщиком, где я получаю неразрешенный внешний символ.

error LNK2019: unresolved external symbol 
   "public: class SpecialType & __cdecl MyClass<class SpecialType>::Foo<class SpecialType,0>(void)" 
   (??$Foo@VSpecialType@@$0A@@?$MyClass@VSpecialType@@@@QEAAAEAVSpecialType@@XZ) referenced in function MyFunction

В чем проблема? Кстати, другие не-enable_if методы хорошо связаны.

1 Ответ

0 голосов
/ 04 февраля 2020

То, как вы объявляете Foo, должно быть названо как Foo<>(), что не идеально.


Теперь я хотел бы добавить другой метод, который будет включен только для определенного параметра шаблона класса.

Альтернативный способ достижения этого - специализировать (производную) часть класса для SpecialType:

struct SpecialType;

template<typename T>
struct MyClassCommon {};

// Generic version.
template<typename T>
struct MyClass : MyClassCommon<T> {
    using MyClassCommon<T>::MyClassCommon;
};

// Specialization for SpecialType.
template<>
struct MyClass<SpecialType> : MyClassCommon<SpecialType> {
    using MyClassCommon<SpecialType>::MyClassCommon;
    SpecialType& foo();
};

Использование:

MyClass<int> a;
// a.foo(); // error: 'struct MyClass<int>' has no member named 'foo'
MyClass<SpecialType> b;
b.foo();
...