[英]How do I restrict a template class to certain built-in types?
這個問題已經討論過幾次,但我發現的所有解決方案要么不起作用,要么基於 boost 的靜態斷言。 我的問題很簡單。 我有一個類,我只想允許真正的類型(double 和 float)。 如果我嘗試使用 float 或 double 以外的類型實例化類,我想要一個編譯時錯誤。 我正在使用 Visual C++ 11。這是我嘗試過的:
template <typename RealType>
class A
{
// Warning C4346
static_assert(std::is_same<RealType, double>::value || std::is_same<RealType, float>::value);
}
template <typename RealType>
class A
{
// Error C2062: type 'unknown' unexpected
static_assert(decltype(RealType) == double || decltype(RealType) == float);
}
有任何想法嗎? 提前致謝!
在你的第一個例子中, static_assert
應該采用第二個參數,這將是一個字符串文字,否則它被視為失敗(編輯:從 C++17 開始刪除第二個參數是合法的)。 這第二個參數不能被默認。
由於以下幾個原因,您的第二個示例不正確:
decltype
旨在用於表達式,而不是用於類型。==
進行比較,正確的方法是您在第一次嘗試使用std::is_same
嘗試的std::is_same
。因此,做您想要實現的目標的正確方法是:
#include <type_traits>
template <typename RealType>
class A
{
static_assert(std::is_same<RealType, double>::value || std::is_same<RealType, float>::value,
"some meaningful error message");
};
此外,我敢打賭您正試圖將您的模板限制為浮點值。 為此,您可以使用特征std::is_floating_point
:
#include <type_traits>
template <typename RealType>
class A
{
static_assert(std::is_floating_point<RealType>::value,
"class A can only be instantiated with floating point types");
};
作為獎勵,以這個在線示例為例。
我見過的一種解決方案是在類型別名中使用std::enable_if
。 就像是:
using value_type = typename std::enable_if<
std::is_same<float, RealType>::value ||
std::is_same<double, RealType>::value,
RealType
>::type;
value_type
僅在RealType
恰好是float
或double
時才存在。 否則,類型未定義且編譯失敗。
不過,我會警告對類型過於嚴格。 模板之所以強大,部分原因在於它們所做的鴨式輸入意味着任何可以按照您想要的方式使用的類型都可以使用。 為了禁止類型而禁止類型通常不會給您帶來太多好處,並且會使事情變得不那么靈活。 例如,您將無法使用更精確的類型,如大十進制類型。
通過這種方式,它還允許對各種類型進行專業化:
template<typename T, typename Enable = void>
class A {
/// Maybe no code here or static_assert(false, "nice message");
};
/// This specialization is only enabled for double or float.
template<typename T>
class A<T, typename enable_if<is_same<T, double>::value || is_same<T, float>::value>::type> {
};
C++20 概念用法
https://en.cppreference.com/w/cpp/language/constraints cppreference 給出了類似的繼承示例,正如我在: 僅接受某些類型的 C++ 模板,並從中猜測我認為特定類的語法將是:
template <class T, class Class1, class Class2>
concept Derived = std::is_same<U, Class1>::value || std::is_same<U, Class2>::value;
template<Derived<MyClass1, MyClass2> T>
void f(T);
但由於編譯器支持,如其他答案中所述,我還無法對此進行測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.