2017-04-04 7 views
5

これは、ゼロ以外の型のベアボーンです。C++の従属型、非ゼロ型

template<typename T> 
struct NonZero { 
    T val; 
}; 

それはタイプTのリテラルを取り、静的にそれがゼロ以外だと、その後valに割り当てるかどうかを確認するためにどのNonZeroのコンストラクタを作ることが可能かどう私の質問はあります。

NonZero<int> n(0); // compilation error 
NonZero<int> n(1); // ok 

また、非ゼロ型を実現する良い方法がありますか?

+0

私の理解するために、具体的な実装では、唯一のテンプレートの特殊化によって提供することができます;それは何が望ましいのですか? – Codor

+0

'NonZero n(var)'も可能なはずなので、もっと簡単な方法があるのだろうかと思っていました。 – Sherushe

答えて

3

別のオプションは、の値をチェックすることですconstexprコンストラクタでは0です。

template<typename T> 
struct NonZero { 
    const T value; 
    constexpr NonZero(const T val) : 
     value(val != 0 ? val : throw std::runtime_error("should be non-zero")) 
    {} 
}; 

使用法:

NonZero<int> v(1);   // OK 
NonZero<int> v2(0);   // Compiles OK, but throws in run-time 
constexpr NonZero<int> v3(1); // OK 
constexpr NonZero<int> v4(0); // Compilation error 

この方法は、変数constexprにのみ適用されますが、はるかに簡単です。

constexprコンストラクタでstructを使用する代わりに、まったく同じ考えでconstexpr関数またはユーザー定義のリテラルを使用できます。

+0

gccの 'expression ''が定数式ではないというエラーが表示されます。問題のアイデアはありますか? – Sherushe

+2

私はとても愚かです、私のコメントはもちろんですが、変数が0で構築されているときにコンパイルエラーが発生します。とにかくありがとう、それはまさに私が探していたものでした。 – Sherushe

+1

@Sherusheよろしくお願いします。答えるのはすばらしい質問でした。 – alexeykuzmin0

5

値はコンパイル時に知られているので、あなたはそれをテンプレート引数を作成し、使用することができstd::enable_if

template<typename T, T x> 
struct NonZero { 
    const static std::enable_if_t<x != T(0), T> value = x; 
}; 

使用法:

int x = NonZero<int, 1>::value; // OK 
int x2 = NonZero<int, 0>::value;// Compilation error 
+0

私はむしろ 'typename T、Tx'と' x!= T(0) 'を好むでしょう - それ以外は、nice ... – Aconcagua

+0

@Aconcagua指してくれてありがとう、コードを更新します – alexeykuzmin0

+0

ありがとう、私は気付いた私の質問では少し曖昧です。 lvalue intを持つコンストラクタも必要でした。 – Sherushe

1

もう一つのアプローチを考えてみましょう。これは、値を引数として取るコンストラクタを提供します。

コンストラクタをテンプレート化して、その値をテンプレート引数として渡すことがコアの考えです。残念ながら、それは簡単な方法でこれを行うことは不可能ですが、私たちはthis questionからの回避策を使用することができます。

template<typename T> 
struct NonZero { 
    const T value; 

    template<T x> 
    NonZero(std::integral_constant<std::enable_if_t<x != T(0), T>, x>) : value(x) { 
    } 
}; 

使用法:

auto v = NonZero<int>(std::integral_constant<int, 1>()); // OK 
auto v2 = NonZero<int>(std::integral_constant<int, 0>()); // Compilation error 
関連する問題