No więc tak, w offline'owej ankiecie wyszło mi 2:2, dwie osoby za enable_if, dwie za static_assert, także dlaczego by nie zapytać forum ;)
Problem i uproszczony przykład, mam klasę, która przechowuje wartość generyczną. Dla jednego, jedynego typu chce uniemożliwić zawołanie jednej metody. I mogę to zrobić na przynajmniej dwa sposoby, każda ma swoje wady i zalet.
enable_if
template<typename T>
struct Holder
{
T getValue() const { return m_value;}
template<typename U = T, typename = typename std::enable_if<!std::is_same<U, bool>::value>::type>
const T& getRefValue() const { return m_value; }
T m_value;
};
static_assert
template<typename T>
struct Holder
{
T getValue() const { return m_value;}
const T& getRefValue() const
{
static_assert(!std::is_same<T, bool>::value, "Calling getRefValue for bool is not allowed");
return m_value;
}
T m_value;
};
Dzięki enable_if jeśli mamy dobry edytor dostaniemy błąd już na etapie pisania kodu. Ale za to dzięki static_assert będziemy mieli czytelniejszy błąd kompilacji jeśli już ktoś niepoprawnie metody użyje. Pojawił się też argument że static_assert jakiś taki czytelniejszy. A co o tym myśli forum 4p? Ja tam wolę enable_if, vim take rzeczy ogarnia bez problemu.
I jeszcze bonusowe rozwiązanie, zamiast enable_if można by zmajstrować zamiennik z którym już każdy edytor powinien sobie poradzić:
template<typename T, typename TSelf>
struct ValueRefAccess
{
const T& getRefValue() { return static_cast<const TSelf*>(this)->m_value; }
};
template<typename T, typename TSelf>
struct ValueRefAccess <bool, TSelf>
{
};
template<typename T>
struct Holder : ValueRefAccess<T, Holder<T>>
{
T getValue() const { return m_value;}
T m_value;
};