1

I have a class defined by two templates.

template<typename A, typename B> my_class {
private:
    A value;

public:
    operator A () {
        return this->value;
    }
};

I want to define an implicit conversion between the class and the first type in the template, but only for a specific second type on the template. Since A is a C++ primitive type I can't define the conversion on that side. I tried std::enable_if like this

operator typename std::enable_if<std::is_same<B, specific_B_type>::value, NumT>::type () {
    return this->value;
}

but I get the compile error

Error   C2833   'operator type' is not a recognized operator or type    dimensional_analysis

Is there any way to do this without having to define the entire class specialized for B = specific_B_type?

mbtg
  • 95
  • 1
  • 8
  • Unfortunately, I just discovered that my answer doesn't actually work... It seems that this disables the whole class instantiation, not just the operator... Could you unaccept it, so I can delete it? :) – Knoep Oct 20 '17 at 00:02
  • Okay, found another (much simpler) solution. Is that still what you want? – Knoep Oct 20 '17 at 00:14
  • I'm currently using the first solution you gave `template::value, void>::type>`. It seems to work but I may not have tested it thoroughly enough. What is your best solution? Thanks in advance! – mbtg Oct 21 '17 at 02:02
  • Have you tried creating an instance of the class, where `B != specific_B_type`? I seems that selectively disabling member functions based on class template parameters doesn't work, as it is not possible to have a class with a ill-defined member function even if that function is never used. – Knoep Oct 21 '17 at 11:01
  • What the best solution is depends on your use case. If all you want is to get a compile time error if you try to use the implicit conversion and `B != specific_B_type`, then you should go with my new solution. It is simple and allows you to specifiy a custom error message. If you want something more complicated, like allowing implicit conversion for some `B` and explicit conversion otherwise, you can check out the solutions in the link I posted. All of them are, however, somewhat more involved. – Knoep Oct 21 '17 at 11:08
  • Ok, I tested my code a bit more and discovered that your first solution worked well when compiled with Visual C++ 14.0 but failed with GCC 7.2.0. Since I want both to work I'm going to use the inheritance described in the question you [linked](https://stackoverflow.com/questions/12117912/add-remove-data-members-with-template-parameters). Thanks a lot for your help! – mbtg Oct 24 '17 at 00:04
  • Have a look at [this](https://stackoverflow.com/questions/46907372/conditionally-compile-a-conversion-operator-based-on-numeric-template-parameter#46907524) question which just came out. It seems you can salvage my first solution by copying the class template paramter into a dummy function template parameter. You learn something new every day :) – Knoep Oct 24 '17 at 10:30

1 Answers1

1

You can use a static_assert to check if the conversion should be allowed:

operator A() 
{
    static_assert(std::is_same<B, specific_B_type>::value, "No conversion possible");    
    return this->value;
}

However, that means you cannot have an explicit conversion to A if B is not specific_B_type. If you need that, you can have a look at the answers of this question about adding and removing members based on template parameters.

Knoep
  • 858
  • 6
  • 13