0

I'm trying to implement managed->native converter in c++/cli. There are about 20 types to convert so I'm trying to use templates for this. The problem is that I should handle values types and reference types differently.

Here is what I'm trying to implement (this code is OK. At least it compiles):

#define val_t_constraint(T) std::enable_if_t<std::is_integral<T>::value || std::is_floating_point<T>::value, T>
#define ref_t_constraint(T) std::enable_if_t<!std::is_integral<T>::value && !std::is_floating_point<T>::value, T>

template<class TElementIn, class TElementOut = TElementIn>
static val_t_constraint(TElementOut) convert(const TElementIn& native)
{
    return (TElementOut)native;
}

template<class TElementIn, class TElementOut = TElementIn>
static ref_t_constraint(TElementOut)^ convert(const TElementIn& native)
{
    return gcnew TElementOut();
}

template<class TElementIn, class TElementOut = TElementIn>
static array<val_t_constraint(TElementOut)>^ convert(const std::vector<TElementIn>& native)
{
    auto arr = gcnew array<TElementOut>(1);
    arr[0] = convert<TElementIn, TElementOut>(native[0]);
    return arr;
}

template<class TElementIn, class TElementOut = TElementIn>
static array<ref_t_constraint(TElementOut)^>^ convert(const std::vector<TElementIn>& native)
{
    auto arr = gcnew array<TElementOut^>(1);
    arr[0] = convert<TElementIn, TElementOut>(native[0]);
    return arr;
}

But when I'm trying to specialize some template, for example like this:

template<>
static array<ref_t_constraint(Guid)^>^ convert(const std::vector<char>& native)
{
    return gcnew array<Guid^>(1);
}

I got an error "error C2912: explicit specialization 'cli::array ^Baz::convert(const std::vector> &)' is not a specialization of a function template".

Constraints through unused function parameter give me another error - template function specialisations cannot have default parameters. Constraints through additional template arguments don't work. I guess because of the SFINAE implementation in VC++120.

Is it possible to implement such solution? Maybe I'm doing something wrong? I'm using VC++120.

Dmitry Katkevich
  • 883
  • 7
  • 26
  • Are you sure about 'constaint' (rather than 'constraint')? not that it matters, but English speakers may be confused. – Walter Sep 05 '16 at 08:44
  • If you want to treat values and referenced differently, why then are you not using the respective type traits, but something completely unrelated (namely `is_integral` and `is_floating_point`)? – Walter Sep 05 '16 at 08:48
  • @Walter When I saw "handle values types and reference types differently" I meant that in c++\CLI if you want have array of built-in simple type (like int, float or bool) you should create it like this: gcnew array() without '^' wereas other types (reference type) should be created using array syntax (with '^') – Dmitry Katkevich Sep 05 '16 at 08:54

1 Answers1

0

I've incorrectly specialized the template. The correct version:

template<>
static array<Guid> convert<char, Guid>(const std::vector<char>& native)
{
    auto arr = gcnew array<Guid>(1);
    arr[0] = convert<char, Guid>(native[0]);
    return arr;
}
Walter
  • 44,150
  • 20
  • 113
  • 196
Dmitry Katkevich
  • 883
  • 7
  • 26