Условная компиляция метода-члена void с использованием enable_if
,
#include <iostream>
#include <type_traits>
using namespace std;
template<typename T>
struct MyClass{
void hello( void) {
hello(std::is_same<T,bool>());
}
void hello(std::true_type){
cout<<"hello only for bools"<<endl;
}
};
int main(int argc, char** argv){
MyClass<bool> myclass1;
myclass1.hello();
MyClass<float> myclass2;
//myclass2.hello(); //throws error as it should
return 0;
}
Я написал приведенный выше код после прочтения специализации метода enable_if. Я хочу, чтобы метод hello() существовал, только если аргументом шаблона является bool, и он работает. Однако я сталкиваюсь с проблемами, когда пытаюсь решить ту же проблему, используя enable_if. У меня есть следующий код. Любая помощь приветствуется. Если enable_if не подходит для этой работы, что обычно используется?
#include <iostream>
#include <type_traits>
using namespace std;
template<typename T>
struct MyClass{
typename std::enable_if<std::is_same<T,bool>::value, void>::type
hello(void)
{
cout<<"hello only for bools"<<endl;
}
};
int main(int argc, char** argv){
MyClass<bool> myclass1;
myclass1.hello();
MyClass<float> myclass2;// compilation error. Don't know how to solve
//myclass2.hello(); //I want only this line to cause compilation error
return 0;
}
РЕДАКТИРОВАТЬ: я нашел решение моего вопроса в ответ jpihl в std::enable_if для условной компиляции функции-члена. Но кто-нибудь может объяснить, почему вышесказанное не работает?
#include <iostream>
#include <type_traits>
using namespace std;
template<typename T>
struct MyClass{
template<class Q = T>
typename std::enable_if<std::is_same<Q, bool>::value, void>::type hello()
{
cout<<"hello only for bools"<<endl;
}
};
int main(int argc, char** argv){
MyClass<bool> myclass1;
myclass1.hello();
MyClass<float> myclass2;// throws errow. Don't know how to solve
myclass2.hello(); //
return 0;
}
1 ответ
Ваша первая попытка с enable_if
не работает, потому что SFINAE применяется в разрешении перегрузки шаблонов функций (или функций-членов), где исключает специализацию шаблона функции из набора перегрузки, когда эта специализация не может быть скомпилирована.
Член hello
, с вашей первой попытки, не является шаблоном функции-члена. У него нет параметров шаблона. Это просто функция- член шаблона класса.
Тип возвращаемого значения формулируется enable_if
выражение, которое вызовет ошибку компиляции, если параметр шаблона класса T
не создан как bool
, Это не превращает функцию-член в шаблон. СФИНА не имеет приложения. Как только вы объявите MyClass<float> myclass2
, специализация MyClass<T>
и все его члены полностью определены. Функция-член hello
этой специализации должны быть созданы, и с T
знак равно float
попытка сделать это не должна компилироваться.
Во второй, удачной попытке, hello
шаблон функции-члена (шаблона класса) У него есть параметр шаблона, Q
, который по умолчанию = T
, Так что SFINAE применяется, и вы можете использовать его с enable_if
в намеченном порядке. Вы можете объявить MyClass<float> myclass2
без ошибок, потому что это не приводит к созданию экземпляра элемента шаблона MyClass<float>::hello<Q>
Поскольку вы написали только одну перегрузку hello
существует только одна специализация шаблона функции-члена для любого выбора Q
, когда Q
знак равно bool
та единственная специализация выживает и myclass1.hello()
скомпилирует. когда Q
знак равно bool
SFINAE устраняет эту единственную специализацию и myclass2.hello()
не компилируется.
Чтобы четко определить, как SFINAE во втором случае работает при создании шаблона функции-члена, рассмотрим следующее:
MyClass<float> myclass2;
myclass2.hello<bool>();
Это хорошо; в то время как с другой стороны:
MyClass<bool> myclass1;
myclass1.hello<float>();
не компилируется.