Я пытаюсь добиться проверки типов параметров класса шаблонов, запретив неявные преобразования типа, такие как string-> bool, тем самым бросая ошибку компиляции. Конкретный сценарий является простым:
#include <iostream>
#include <string>
using namespace std;
template <class T>
class myPair {
T a, b;
public:
myPair(T first, T second ) {
a = first;
b = second;
}
void test();
};
typedef myPair<bool> boolParm;
template<class T>
void myPair<T>::test() {
if(a == true) {
cout << "a is true" << endl;
} else {
cout << "a is false" << endl;
}
if(b == true) {
cout << "b is true" << endl;
} else {
cout << "b is false" << endl;
}
}
int main() {
boolParm myObj(false, "false");
myObj.test();
return 0;
}
Вывод вышеупомянутого сценария нежелателен, так как пользователь может непреднамеренно передать два разных типа: bool и string и получить первый как false (правильный, поскольку он передан как bool), но второй будет true (неверно, поскольку неявное преобразование типа из строки для bool). Я хочу ограничить код пользователя в main(), чтобы бросать ошибки компиляции и запрещать параметры string/int для передачи в конструкторе. Это должно позволить только bool. Я попытался использовать перегруженный конструктор myPair (сначала bool, строка second), но он не совпадал, так как я предполагаю, что неявное преобразование типа из string-> bool происходит до вызова конструктора. Есть ли какое-либо решение, использующее специализированные шаблоны в этом сценарии? Любая помощь высоко оценена Спасибо
Один из способов - добавить шаблонную фабричную функцию для создания myPair.
template <typename T>
myPair<T> makeParam(T a, T b) {
return myPair<T>(a, b);
}
Это не скомпилируется с неопределенным параметром шаблона T, если типы не совпадают. Вы можете расширить это с помощью специализированных шаблонов, явно запрещающих определенные типы для T. Ваша основная функция будет выглядеть примерно так:
int main() {
boolParm myObj = makeParam(false, "false");
myObj.test();
return 0;
}
Альтернативно изменить конструктор:
template <typename U, typename V>
myPair(U a, V b);
И специализироваться по мере необходимости
Пример такой специализации:
template <class T>
class myPair {
T a, b;
public:
template <typename U, typename V> // generic version
myPair(U first, V second)
{
// intentionally fail to compile
static_assert(false, "don't support generic types");
}
template <> // template specialization
myPair(T first, T second)
{
// explicitly require exactly type T
a = first;
b = second;
}
};
На самом деле это странное поведение на первый взгляд; но, насколько я могу судить, вы не можете запрещать это, но не для примитивных типов, таких как bool
.
Неявное преобразование параметров происходит до того, как вы получите ответ на него, и кажется, что существует неявное преобразование примитивного типа из char const *
в bool
.
См. Также, например, этот другой вопрос: почему строка с кавычками соответствует сигнатуре метода bool перед строкой std :: string?