4

可能だと思って、ここで手足に出かけますが、よくわかりません。基本的に私が探しているのは、コンパイル時にデフォルトのコンストラクターを使用するか、参照によって1つの引数を取るコンストラクターを使用するかを切り替える方法です。

すなわち

T* create<T>()
{
    return new T(1); // if possible
}

T* create<T>()
{
    return new T(); // fallback to here
}

VS2010コンパイラを使用していますが、サポートされていませんstd::is_constructibleが、使用できますdecltype

VS2012 type_traitsヘッダーを掘り下げてstd::is_constructible実装を確認したところ、少し好転しました。人々がそのようにコードを書く方法がわかりません。ヘッダーは、私が今まで見た中で最も複雑なコードです。とにかく、それがdecltypeを使用しているのを見て、それは私に考えさせられました、うまくいけば、より経験豊富な誰かが私に答えを提供することができます。

@ipcの回答を確認した後、次のコードに落ち着きました

// std::declval is not supported by VS2010
template <typename T> typename std::add_rvalue_reference<T>::type declval();

template <class T, class R0>
decltype(new T(declval<R0>()))
createInstance_(R0& r0, int = 0)
{
    return new T(r0);
}

template <class T, class R0>
T*
createInstance_(R0&, ...)
{
    return new T();
}

上記のコードは機能しますが、IntelliSenseエンジンを混乱させます。とにかく、デフォルトの引数を使用するだけで余分な関数を省略できるのは良いことだと思いました。このコードをVS2010でテストしましたが、正常にコンパイルされ、期待どおりに実行されます。

4

1 に答える 1

5

そこでコンパイルされるかどうかを確認するVS2010はありませんが、以下はあなたの例と一致します。

template <typename T> // if std::declval is not supported by VS10
typename std::add_rvalue_reference<T>::type declval();

template <typename T>
decltype(new T(declval<std::string>()))
create_(std::string param, int) { return new T(param); }
template <typename T>
T * create_(std::string, ...) { return new T(); }

template <typename T>
T * create(std::string param) { return create_<T>(param, 0); }

int main()
{
  std::cout << *create<int>("a") << '\n';
  std::cout << *create<std::string>("b") << '\n';
}

出力:

0
b
于 2012-12-05T19:35:59.123 に答える