2016-12-16 5 views
3

Следующий пример кода иллюстрирует мою проблему:Как специализироваться с шаблоном VARIADIC класса

#include <array> 
#include <vector> 
#include <iostream> 
#include <type_traits> 

namespace Vector 
{ 
    namespace Intern 
    { 
     template <typename T1, typename ...T2> 
     struct Traits; 

     // How can I specialize here so that Memory is being assigned properly?? 
     template <typename T1, int N> 
     struct Traits<T1, int> { 
      static constexpr bool Static = 1; 
      using Memory = std::array<T1, N>; 
     }; 

     template <typename T1> 
     struct Traits<T1> { 
      static constexpr bool Static = 0; 
      using Memory = std::vector<T1>; 
     }; 
    } 

    template <typename T1, typename ...T2> 
    class Object 
    { 
     public : 
      void printd() 
      { 
       std::cout << "Is Static: " << Traits::Static << std::endl; 
      } 
     private: 
      using Traits = Intern::Traits<T1, T2...>; 
      using Memory = typename Traits::Memory; 

      Memory m_memory; 
    }; 

    template <typename T1, typename ...T2> 
    static auto Create(T2&& ...ln) -> decltype(auto) 
    { 
     return new Object<T1, T2...>(); 
    } 
} 

int main() 
{ 
    auto static_vector = Vector::Create<int>(10); 
    static_vector->printd(); 

    auto active_vector = Vector::Create<int>(); 
    active_vector->printd(); 
} 

Я хотел бы знать, как я могу специализироваться черты структуры так, что тип памяти правильно назначен станд :: массив с N, установленным в 10 в приведенном выше примере.

+0

что вы хотите тип static_vector быть? –

+0

Как вы хотите вывести 'N' здесь? Зачем вам нужен вариационный шаблон, а не просто два параметра? – Holt

ответ

1

Вы не можете использовать целое число напрямую, но вы можете обернуть целое число в тип. Это можно сделать, используя , например. std::integral_constant:

template <typename T1, typename T2, int N> 
struct Traits<T1, std::integral_constant<T2, N>> { 
    static constexpr bool Static = 1; 
    using Memory = std::array<T1, N>; 
}; 

template <typename T1> 
struct Traits<T1> { 
    static constexpr bool Static = 0; 
    using Memory = std::vector<T1>; 
}; 


auto static_vector = Vector::Create<int, std::integral_constant<int, 10>>(); 
+0

Это близко к решению, которое я искал. Однако существует ли способ использования std :: integral_constant, как вы использовали, но не меняя подпись функции Vector :: Create? Другими словами, можно ли, например, расширить этот код таким образом, чтобы я мог хранить подпись Vector :: Create (10)? – vixiv

+1

@vixiv Я так не думаю. Я не знаком с тем, что предлагает 'constexpr' (не используя компилятор, который его поддерживает), но я бы предположил, что после того, как вы войдете в аргумент аргумента, вернитесь к аргументам шаблона. Или, может быть, с пользовательским литералом может быть, но это все равно изменит синтаксис. – Angew

1

Держите это просто:

#include <array> 
#include <vector> 
#include <iostream> 
#include <type_traits> 

namespace Vector 
{ 
    struct VariableSize {}; 
    template<std::size_t N> struct FixedSize {}; 

    template<typename T, std::size_t N> 
    auto Create(FixedSize<N>) 
    { 
     return std::array<T, N>(); 
    } 

    template<typename T, std::size_t N> 
    auto Create(VariableSize) 
    { 
     return std::vector<T>(); 
    } 
} 

int main() 
{ 
    auto static_vector = Vector::Create<int>(Vector::FixedSize<10>()); 

    auto active_vector = Vector::Create<int>(Vector::VariableSize()); 
} 
+0

Ваш код действительно прост. Однако факт заключается в том, что я надеялся повторно использовать (оптимизировать распределение памяти) в каком-то внутреннем коде без изменения лицевой стороны Vector :: Create signature. – vixiv

+1

@vixiv Боюсь, что это невозможно. Вы не можете изменить тип возвращаемого значения функции, изменив ее аргумент. Даже функция 'constexpr' может это сделать. –