Russian Qt Forum
Ноябрь 23, 2024, 08:07 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: SFINAE для методов шаблонных классов  (Прочитано 4529 раз)
Eugene Efremov
Гость
« : Апрель 09, 2008, 01:35 »

Имеем следующий пример неработающего кода:

Код:
struct foo1 { typedef int val; };
struct foo2 { };

template <class foo> struct bar
{
typename foo::val f() {return 10; }
// other...
};

int main()
{
bar<foo1> f1;
bar<foo2> f2; // error: no type named `val' in `struct foo2'

int i = f1.f();
//f2::f newer used...
}

Есть идеи, как можно поизвращаться с enable_if и ему подобными, чтобы заставить это дело компиляться, игнорируя отсутствие foo::val для bar<foo2>?
Записан
Tonal
Гость
« Ответ #1 : Апрель 09, 2008, 08:56 »

Код:
#include <iostream>

struct yes {
  char dummy;
};
struct no {
  yes dummy[2];
};         

//Распознование, определён ли в классе typedef val
template <class T>
struct has_val {
  template <class Y>
  struct check {
    typedef yes res;
  };
  template <class U>
  static typename check<typename U::val>::res test_val(const U*);
  static no test_val(...);

  enum {value = sizeof(yes) == sizeof(test_val((T*)0))};
};

template <class foo>
struct bar {
  //Выбор возвращаемого значения и selector-а
  template <class T, bool enable>
  struct type_select {
    typedef typename T::val type;
    typedef const T* selector;
  };

  //Возвращаемое значения и selector по умолчанию
  template <class T>
  struct type_select<T, false> {
    typedef long type;
    typedef const void* selector;
  };

  typedef typename type_select<foo, has_val<foo>::value>::type ret_type;
  typedef typename type_select<foo, has_val<foo>::value>::selector selector;

  //Основная реализация
  ret_type f(const foo*) {
    return 10;
  }

  //Реализация по умолчанию
  ret_type f(const void*) {
    return 5;
  }

  //Диспетчер
  ret_type f() {
    return f((selector)0);
  }
  // other...
};

//Тестовый пример
using std::cout;
using std::endl;

struct foo1 {
  typedef int val;
};

struct foo2 {
};

int main() {
  bar<foo1> f1;
  bar<foo2> f2;
 
  cout<<f1.f()<<endl;
  cout<<f2.f()<<endl;
}
На boost::enable_if сам переводи. Улыбающийся

P.S. Блин, насколько всё же проще писать подобное на Haskell, где встроенное сопоставление с образцом...
« Последнее редактирование: Апрель 09, 2008, 08:57 от Tonal » Записан
Eugene Efremov
Гость
« Ответ #2 : Апрель 09, 2008, 19:09 »

Код:
[...skip...]

Спасибо!

P.S. Блин, насколько всё же проще писать подобное на Haskell, где встроенное сопоставление с образцом...

Ну дык ёлы-палы... Увидев конструкции, порождаемые этим самозародившимся функциональным франкенштейном, волей-неволей задумаешься — какой казни следует предать Страуструпа и КО а строит ли оно того... :-)
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.109 секунд. Запросов: 20.