C ++: предоставление функции класса в шаблонном классе при наличии именованного члена в его шаблонном типе?

Я пытаюсь сделать следующее: шаблонный класс должен предоставлять некоторые функции, зависящие от того, содержит ли тип, для которого он был создан в шаблоне, переменную-член с заданным именем. В качестве примера приведен следующий псевдокод, который должен предоставлять "printid ()" только тогда, когда шаблонная структура / класс имеет член с именем "id":

#include <iostream>
#include <type_traits>

struct A { int id; };
struct B { };

template<typename T>
class foo
{
  T myvar;

public:
  #if exists T.id   (or the alternative: #if exists myvar.id)
  printid() { std::cout << "I have element id."; }
  #endif
};

int main(){
  foo<A> ok;
  ok.printid();   // should compile and execute

  foo<B> nok;
  nok.printid();  // should not compile
  return 0;
}

Копаясь в SFINAE, traits, std :: enable_if и StackOverflow, я думаю, что это можно сделать ... как-нибудь. Но мне почему-то не удается объединить enable_if со следующим фрагментом из вопроса Как определить, есть ли в классе конкретная переменная-член?:

template<typename T, typename = void>
struct has_id : std::false_type { };

template<typename T>
struct has_id<T, decltype(std::declval<T>().id, void())> : std::true_type { };

Любая помощь приветствуется.


person BaCh    schedule 27.01.2016    source источник


Ответы (1)


Ага, это возможно. Вот пример:

template<typename T>
class foo
{
  T myvar;

public:
  template <class _T = T,
            class = typename std::enable_if<
                      !std::is_function<decltype(_T::id)>::value>
                    ::type>
  void printid() { std::cout << "I have element id."; }
};

В частности, обратите внимание, как мы «принимаем» T как _T, чтобы не накладывать ограничения на параметр шаблона класса (что сделало бы сам класс некомпилируемым). Вместо этого мы создаем новую независимую функцию-член шаблона, которая ничего не заставляет T сама, а просто «случайно» использует ее как аргумент по умолчанию. Это ключевая часть.

person Yam Marcovic    schedule 27.01.2016
comment
Работает как задумано. Я бы никогда не узнал, как объявить это вуду. Обернуть это определение, чтобы сохранить набор для нескольких функций, теперь проще простого. Большое Вам спасибо. - person BaCh; 27.01.2016