2016-12-02 1 views
3

Я пытаюсь избежать концепций на мастер ветви моих проектов, так что мне нужно какое-то альтернатива с type_trait:Перегрузка члены от шаблонного класса на логическом значении

Мне нужен класс, который несколько несколько функций изменятся в зависимости от значения bool.

Кто-то уже предложил мне разбить мой класс, но этот случай здесь не имеет смысла. В некотором контексте это пул, в котором функция удаления и некоторые другие будут изменены, если тип объекта пула может быть общим или нет.

Поэтому я попытался использовать std::enable_if, но все еще есть некоторые ошибки (Я хочу, чтобы декларация и реализация были отдельными).

#include <type_traits> 

template < typename Object, bool Shared = false > 
class Foo { 

    template < bool S = Shared, typename std::enable_if<S>::type* = nullptr > 
    void bar(); 

    template < bool S = Shared, typename std::enable_if<!S>::type* = nullptr > 
    void bar(); 
}; 

template < typename Object, 
      bool Shared > 
template < bool S, typename std::enable_if<S>::type* = nullptr > 
void Foo<Object, Shared>::bar() { 
    //do something 
} 


template < typename Object, 
      bool Shared > 
template < bool S, typename std::enable_if<!S>::type* = nullptr > 
void Foo<Object, Shared>::bar() { 
    //do nothing 
} 

int main() { 

    Foo<int> test; 
    return 0; 
} 

Test3.cpp:16:33: error: default argument for template parameter for class enclosing ‘void Foo<Object, Shared>::bar()’ 
void Foo<Object, Shared>::bar() { 
           ^
Test3.cpp:24:33: error: default argument for template parameter for class enclosing ‘void Foo<Object, Shared>::bar()’ 
void Foo<Object, Shared>::bar() { 

EDIT: Убрана ошибка копирования/вставки

ответ

4

1. Квалификация имени класса (т.е. Foo<Object, Shared>::) следует исключить для функции члена декларации внутри определения класса.

2. Default template arguments не допускаются для определения классов элементов вне класса, просто удалите их.

Параметры по умолчанию не допускаются

  • в определении вне-класса шаблона членов (они должны быть , содержащуюся в декларации внутри тела класса)

Тогда

template < typename Object, bool Shared = false > 
class Foo { 

    template < bool S = Shared, typename std::enable_if<S>::type* = nullptr > 
    void bar(); 

    template < bool S = Shared, typename std::enable_if<!S>::type* = nullptr > 
    void bar(); 
}; 

template < typename Object, 
      bool Shared > 
template < bool S, typename std::enable_if<S>::type* > 
void Foo<Object, Shared>::bar() { 
    //do something 
} 

template < typename Object, 
      bool Shared > 
template < bool S, typename std::enable_if<!S>::type* > 
void Foo<Object, Shared>::bar() { 
    //do nothing 
} 

LIVE

+0

Я нашел что-то довольно круто: https://www.youtube.com/watch?v=aXSsUqVSe2k –

1

Вот код один раз фиксированный (минимальный, рабочий пример):

#include <type_traits> 
#include <iostream> 

template < typename Object, bool Shared = false > 
class Foo { 
public: 
    template < bool S = Shared, typename std::enable_if<S>::type* = nullptr > 
    void bar(); 

    template < bool S = Shared, typename std::enable_if<!S>::type* = nullptr > 
    void bar(); 
}; 

template < typename Object, bool Shared > 
template < bool S, typename std::enable_if<S>::type*> 
void Foo<Object, Shared>::bar() { 
    std::cout << "do something" << std::endl; 
} 

template < typename Object, bool Shared > 
template < bool S, typename std::enable_if<!S>::type*> 
void Foo<Object, Shared>::bar() { 
    std::cout << "do nothing" << std::endl; 
} 

int main() { 
    Foo<int> test; 
    test.bar<>(); 
    test.bar<true>(); 
    return 0; 
} 

Это была проблема дополнительных классификаторов и параметров по умолчанию не будет повторяться в из определений классов.

+0

Спасибо! Мне плохо, что я спросил об этом сейчас ^^ В основном, потому что я сделал ошибку с копией/вставкой для минимального примера. –

1

В качестве дополнительного к сведению, что является гораздо более чистым решением:

#include <type_traits> 
#include <iostream> 

template<bool b> 
using allow_if = typename std::enable_if<b>::type; 

template <typename Object, bool Shared = false> 
class Foo { 
public: 
    template<bool S = Shared> 
    allow_if<S> bar(); 

    template<bool S = Shared> 
    allow_if<!S> bar(); 
}; 

template<typename Object, bool Shared> 
template<bool S> 
allow_if<S> Foo<Object, Shared>::bar() { 
    std::cout << "do something" << std::endl; 
} 

template<typename Object, bool Shared> 
template<bool S> 
allow_if<!S> Foo<Object, Shared>::bar() { 
    std::cout << "do nothing" << std::endl; 
} 

int main() { 
    Foo<int> test; 
    test.bar<>(); 
    test.bar<true>(); 
    return 0; 
} 
+0

Приятно отметить да, спасибо. –

1

Как альтернатива, вы можете использовать тег-диспетчеризацию:

template <typename Object, bool Shared = false> 
class Foo { 
public: 
    void bar() { bar(std::integral_constant<bool, Shared>{}); } 

private: 
    void bar(std::true_type); 
    void bar(std::false_type); 
}; 

template <typename Object, bool Shared> 
void Foo<Object, Shared>::bar(std::true_type) { /**/ } 

template <typename Object, bool Shared> 
void Foo<Object, Shared>::bar(std::false_type) { /**/ } 

Поскольку C++ 17, вы можете использовать if constexpr :

template <typename Object, bool Shared = false> 
class Foo { 
public: 
    void bar() { 
     if constexpr (Shared) { 
      // ... 
     } else { 
      // ... 
     } 
    } 

Таким образом, каждый блок доступен только в правильном варианте:

  • так нет времени выполнения ветви (я ожидаю, регулярная ветвь должна быть оптимизирована в любом случае в вашем случае)
  • не выбран блок может содержать код действителен только тогда, когда эта ветвь будет выбрана (в основном полезны, если она зависит от типа).
Смежные вопросы