Разрешение перегрузки конструктора класса шаблона

У меня есть простая проблема с разрешением перегрузки ctor для шаблона класса:

#include <iostream>
#include <string>

using namespace std;
enum EnumTypeVal { READ, WRITE };

template <class T>
class TemplateClassTest {
public:
TemplateClassTest(const string & stringVal, T typeVal, EnumTypeVal e = READ,
const string & defaultStringVal = "default");
TemplateClassTest(const string & stringVal, const char * charVal);
TemplateClassTest(const string & stringVal, EnumTypeVal e = READ,
const string & defaultStringVal = "default");
private:
T type;
};

template <class T>
TemplateClassTest<T>::TemplateClassTest(const string & stringVal, T typeVal,
EnumTypeVal e,
const string & defaultStringVal)
{
type = typeVal;
cout << "In TemplateClassTest(const string &, T, EnumTypeVal, ""const string &)" << endl;
}

template <class T>
TemplateClassTest<T>::TemplateClassTest(const string & stringVal,
const char * charVal)
{
cout << "In TemplateClassTest(const string &, const char *)" << endl;
}

template <class T>
TemplateClassTest<T>::TemplateClassTest(const string & stringVal, EnumTypeVal e,
const string & defaultStringVal)
{
cout << "In TemplateClassTest(const string &, EnumTypeVal, const string &)"<< endl;
}

typedef TemplateClassTest<long long unsigned int> u32Type;
typedef TemplateClassTest<bool> boolType;

int main()
{
u32Type l("test", "0"); //matches ctor 2
u32Type v("test", 0); // ambiguity between ctor 1 and 2
boolType b("test", "true"); //matches ctor 2
return 0;
}

Второй вызов не может быть скомпилирован из-за ошибки:

Вызов перегруженного ‘TemplateClassTest (const char [5], int) неоднозначен.

Почему int соответствует const char *? Эту ситуацию можно решить, изменив const char * в const string & в ctor 2. Но при этом, boolType b("test", "true") теперь получает соответствие ctor 1 вместо ctor 2.

Мои требования:

  • u32Type v("test", 0) должен соответствовать ctor 1
  • boolType b("test", "true") должен соответствовать ctor 2.

Ограничения:

  • подписи ctor 1 и 3 не могут быть изменены
  • вызовы кода пользователя в main () не могут быть изменены.

Любая помощь высоко ценится .. Спасибо!

1

Решение

Это неоднозначно, потому что 0 является константой нулевого указателя. Константа нулевого указателя может быть неявно преобразована в любой тип указателя -> a преобразование нулевого указателя. Следовательно, ctor 2 является жизнеспособным: TemplateClassTest(const string&, const char*),

Как целочисленный литерал, 0 имеет тип int, Конструктор 1, TemplateClassTest(const string&, T, EnumTypeVal = READ, const string & = "default"), следовательно, требуется преобразование из int в unsigned long long -> ан интегральное преобразование.

Эти два преобразования, преобразование нулевого указателя а также интегральное преобразование, имеют одинаковый ранг (конверсия), отсюда и неоднозначность.


[Conv.ptr] / 1

Константа нулевого указателя — это целочисленное выражение константы prvalue целочисленного типа, которое оценивается как ноль или prvalue типа std::nullptr_t, Константа нулевого указателя может быть преобразована в тип указателя; результатом является значение нулевого указателя этого типа и отличается от любого другого значения указателя объекта или типа указателя на функцию. Такое преобразование называется преобразование нулевого указателя.


Возможное, но безобразное исправление, соответствующее вашим ограничениям, состоит в том, чтобы изменить второй конструктор на:

template<class U,
class V = typename std::enable_if<std::is_same<U, const char*>{}>::type>
TemplateClassTest(const string & stringVal, U charVal);

То есть жадный шаблон конструктора, ограниченный SFINAE только для принятия const char* как второй аргумент. Это сильно ограничивает неявные преобразования, применяемые ко второму аргументу при попытке сопоставить этот ctor.

Внеочередное определение становится:

template <class T>
template<class U, class V>
TemplateClassTest<T>::TemplateClassTest(const string & stringVal, U charVal)
{
cout << "In TemplateClassTest(const string &, const char *)" << endl;
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]