簡體   English   中英

帶有 enable_if 的模板 class 外的方法

[英]Method outside template class with enable_if

我有以下代碼,我想要一個模板 class 在初始化時將模板值檢查為int64_tunint64_t之一。 class 具有在 class 外部實現的GetValue方法。

template <typename T, typename std::enable_if<std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>>::type>
class Class
{
public:
    Class(T value) noexcept :
        cachedValue(value) {}

    T GetValue() noexcept;

private:
    T cachedValue;
};

template <typename T>
T Class<T>::GetValue() noexcept
{
    // placeholder for now.
    return cachedValue;
}

但是,即使在嘗試了其他 SO 帖子的幾個想法之后,我也遇到了來自enable_if的構建錯誤C2955C2956C2976或類似的東西。 我如何讓這個工作?

問題

template <typename T,
          typename std::enable_if<std::is_same_v<T, int64_t>
                               || std::is_same_v<T, uint64_t>>::type>
class Class;

那是結果

template <typename T_OK, void> class Class;

或者

template <typename T_KO, /*Subsitution failure*/> class Class;

這兩個都不正確。

對於不友好的情況(大多數情況下可能就足夠了),您可以簡單地使用static_assert

template <typename T> class Class
{
    static_assert(std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>);
    /// ...
};

否則有幾種變化(我會將條件縮短為cond_v<T>

  • 常見的:(:

     template <typename T, typename = std::enable_if_t<cond_v<T>>> class Class { ///... }; Class<int64_t> ok; Class<float> ko; // doesn't compile, as expected // but might be hijacked: Class<float, void> hijacked; // compile, unexpected
  • 固定的:

     template <typename T, std::enable_if_t<cond_v<T>, int> = 0> class Class { ///... }; Class<int64_t> ok; Class<float> ko; // doesn't compile, as expected
  • 一種允許定制的

    template <typename T, typename = void> class Class; template <typename T> class Class<T, std::enable_if_t<cond_v<T>>> { ///... }; Class<int64_t> ok; Class<float> ko; // incomplete type: doesn't compile, as expected // user might add additional specialization: template <typename T> class Class<std::vector<T>, void> {/*..*/};

    最適用於創建可定制的特征(因為您專門研究整個班級)。

C++20 引入了更短和簡化語法的概念:

  • restreint 允許的類型(有幾種等效的語法)

     template <typename T> requires(cond_v<T>) class Class { /*..*/};
  • 允許定制,采取最好的專業化:

     template <typename T> class Class; // Specialization template <typename T> requires(cond_v<T>) class Class<T> { /*..*/};

您可以使用 @WhozCraing 方法,使用static_assert提供一些消息/指令或使用C++20Concepts ,如下所示

template<class T>
concept ints64 = std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>;
template <typename T> requires(ints64<T>)
struct Class{
    Class(T value) noexcept : cachedValue(value) {}
    T GetValue() noexcept;

private:
    T cachedValue;
};

template <typename T>requires(ints64<T>)
T Class<T>::GetValue() noexcept{
    return cachedValue;
}

int main(){
    return Class<int64_t>{0}.GetValue();//return Class<int>{0}.GetValue(); won't compile

}

在 C++20 之前,還有一種使 class 模板對 SFINAE 友好的傳統方法:

template<typename T, typename = void>
class Class; // <1> you can define it here if the conditions are not satisfied.

template<typename T>
class Class<T, typename std::enable_if<std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>>::type>{
public:
    Class(T value) noexcept :cachedValue(value) {}

    T GetValue() noexcept;

private:
    T cachedValue;
};

int main(){
    Class<int64_t> a = 0; // ok
    Class<uint64_t> b = 0; // ok
    Class<int32_t> c = 0; // incomplete-type. you can define it at <1>.
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM