3 つのサンプル プログラムがあり、そのうち 2 つがコンパイルされ、1 つがコンパイルされません。3 つすべては、コマンド ラインを使用して、g++ 4.8.1 を使用してコンパイルされましたg++ --std=c++11 -Wall -pedantic -o foo foo.cc
。問題のコードは、問題を示すことを目的とした使い捨ての例であり、それ自体で役立つことを意図したものではありません。
std::promise<void>::set_value()
根本的な問題は、引数を取らないという事実を処理するために特殊化を必要とするテンプレート化されたクラスです。この問題は、Foo::_call()
メソッドで発生します。
私が作業したいバージョン、それをバージョン A と呼びますが、失敗します。
#include <future>
template <typename A, typename T>
class Foo
{
private:
std::function<T ()> _f;
std::promise<T> _p;
static void _call(std::function<T ()> &f, std::promise<T> &p) {
p.set_value(f());
}
public:
Foo(std::function<T ()> x) : _f(x) {}
void set_promise() {
_call(_f, _p);
}
};
template<typename A>
inline void Foo<A, void>::_call(
std::function<void ()> &f, std::promise<void> &p)
{
f();
p.set_value();
}
int bar()
{
return 4;
}
void baz()
{
}
int main()
{
Foo<int, int> a(bar);
a.set_promise();
Foo<int, void> b(baz);
b.set_promise();
}
エラーは次のとおりです。
foo.cc:24:53: error: invalid use of incomplete type ‘class Foo<A, void>’
std::function<void ()> &f, std::promise<void> &p)
^
foo.cc:4:7: error: declaration of ‘class Foo<A, void>’
class Foo
^
foo.cc: In instantiation of ‘static void Foo<A, T>::_call(std::function<_Res()>&, std::promise<T>&) [with A = int; T = void]’:
foo.cc:18:21: required from ‘void Foo<A, T>::set_promise() [with A = int; T = void]’
foo.cc:44:19: required from here
foo.cc:11:9: error: invalid use of void expression
p.set_value(f());
^
次のテスト B がコンパイルされます。追加のテンプレート パラメータA
を に取り出しますFoo
。実際には、おもちゃではないクラスがそのパラメーターを必要とするため、これは望ましくありません。
#include <future>
template <typename T>
class Foo
{
private:
std::function<T ()> _f;
std::promise<T> _p;
static void _call(std::function<T ()> &f, std::promise<T> &p) {
p.set_value(f());
}
public:
Foo(std::function<T ()> x) : _f(x) {}
void set_promise() {
_call(_f, _p);
}
};
template<>
void Foo<void>::_call(
std::function<void ()> &f, std::promise<void> &p)
{
f();
p.set_value();
}
int bar()
{
return 4;
}
void baz()
{
}
int main()
{
Foo<int> a(bar);
a.set_promise();
Foo<void> b(baz);
b.set_promise();
}
テスト C もコンパイルされます。_call()
静的メソッドを引き出しFoo
て、テンプレート化された関数にします。_call
に属することを意図しているので、私もこれをしたくありませんFoo
。これは機能しますが、エレガントではありません。
#include <future>
template<typename T>
inline void _call(std::function<T ()> &f, std::promise<T> &p)
{
p.set_value(f());
}
template<>
void _call(std::function<void ()> &f, std::promise<void> &p)
{
f();
p.set_value();
}
template <typename A, typename T>
class Foo
{
private:
std::function<T ()> _f;
std::promise<T> _p;
public:
Foo(std::function<T ()> x) : _f(x) {}
void set_promise() {
_call(_f, _p);
}
};
int bar()
{
return 4;
}
void baz()
{
}
int main()
{
Foo<int, int> a(bar);
a.set_promise();
Foo<int, void> b(baz);
b.set_promise();
}
では、問題は、なぜ A が失敗するのかということです。BまたはCに頼らずにこの問題を解決する方法はありますか?