2016-03-30 20 views
2
私はこのプログラムをコンパイルしようとしている

(それはhereを生きる参照)明らかにparam_typeコンストラクタがランダムな分布に対して明示的になるのはなぜですか?</p> <pre><code>int main() { std::random_device engine; std::uniform_int_distribution<size_t> dis; std::cout << dis(engine, {0, 5}) << std::endl; } </code></pre> <p>をしかし、それはエラーメッセージで失敗します:

error: converting to 'const std::uniform_int_distribution<long unsigned int>::param_type' from initializer list would use explicit constructor 'std::uniform_int_distribution<_IntType>::param_type::param_type(_IntType, _IntType) [with _IntType = long unsigned int]' 
    std::cout << dis(engine, {0, 5}) << std::endl; 

、それはparam_type防止の明示的なコンストラクタがあります私たちはこれをやっていません。しかし、なぜそれを第一に明示的に指定するのですか?書き込みが必要な場合は冗長で愚かです

std::cout << dis(engine, decltype(dis)::param_type(0, 5)) << std::endl; 

これについての説明はありますか?また、param_typeコンストラクタが標準で明示的であるとすれば、どのように簡潔でエレガントな方法で私が望むものを達成することができますか?実際には、disを呼び出すたびに範囲が異なることに注意してください。したがって、建設時間の範囲をdisにすることは役に立ちません。

答えて

3

デフォルトの引数があるため、明示的です。変換コンストラクタではない1つの引数を取るコンストラクタは明示的でなければなりません。

標準では、デフォルトの引数が2つのコンストラクタが1つ必要であるため、すべてのケースが明示的です。明示的でない2引数のコンストラクタ、明示的な1引数のコンストラクタ、および非明示的な0引数のコンストラクタを強制することが改善されます。しかし、その船は航海しました。

問題を回避することができます。

template<class...Args> 
struct construct_params_t { 
    std::tuple<Args&&...> data; 
    construct_params_t(Args&&...args):data(std::forward<Args>(args)...){} 

private: 
    template<class T, std::size_t...Is> 
    T create(std::index_sequence<Is...>){ 
    return T(std::get<Is>(std::move(data))...); 
    } 
public: 
    template<class T> 
    operator T()&&{ 
    return create<T>(std::index_sequence_for<Args...>{}); 
    } 
}; 
template<class...Args> 
construct_params_t<Args...> construct_from(Args&&...args) { 
    return {std::forward<Args>(args)...}; 
} 

今あなたが行うことができます:

int main() { 
    std::random_device engine; 
    std::uniform_int_distribution<size_t> dis; 
    std::cout << dis(engine, construct_from(0, 5)) << std::endl; 
} 

を基本的には、construct_from(a,b,c)はほとんど何を構築するために使用することができ、それを構築するときにその名前を言及することなく、そう明示的に行います。

Live example

このように構成されたオブジェクトは移動可能でなければならず、RVO elisionでは実際に移動させるべきではありません。

戻り値construct_fromの格納はお勧めしません。

+0

私の意見では、 'param_type'コンストラクタがデフォルト引数を持つことはあまり意味がありません。通常、 'param_type'を使用する必要があるのは、デフォルトが適用されないことを意味します。あなたが設計した 'construct_from()'はハッキリしています。はい、私はトリッキーなC++が好きです:)私は[Happy Hacking C++](https://github.com/Lingxi-Li/Happy_Hacking_CXX)プロジェクトに入れます。しかし、実際には、 'decltype(...):: param_type'に固執します。 – Lingxi

関連する問題