Условная компиляция метода-члена 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>();

не компилируется.

Вот документация СФИНАЕ

Другие вопросы по тегам