std::function
でいくつかの異なる機能を共有するクラスを作成しています(少なくともクラスは多くの点で似ています)。テンプレートパラメータ(つまりstd::function<void (std::string&)>
)を指定してstd::function
をインスタンス化することはすべてわかっていますが、これは自分のクラスでも同じです。私は例外がありますが、単一の関数を返す値がvoid(std::function<"return value" ("parameters">
)の場合、私のクラスに特化したいと考えています。私はコンパイル時にこれを行う必要があり、私はちょうどそれがうまく動作するようにすることはできません。ここでは説明のためのいくつかのテストコードは次のとおりです。コンパイル時の型の特殊化
#include <iostream>
#include <type_traits>
template <typename T> class Test { };
template <typename Ret, typename... Args>
class Test<Ret (Args...)>
{
public:
Ret operator()(Args...)
{
if(std::is_void<Ret>::value)
{
// Do something...
}
else /* Not a void function */
{
Ret returnVal;
return returnVal;
}
}
};
int main(int argc, char * argv[])
{
Test<void (char)> test;
test('k');
}
あなたは明確に(すなわちvoid returnVal;
)コンパイラは、上記の試験で「他」の枝を削除しない場合は、私のコードは無効値を作成しようと、見ることができるように。問題は、私はコンパイルエラーになってしまうので、コンパイラはブランチを削除しないことです:
./test.cpp: In instantiation of ‘Ret Test::operator()(Args ...) [with Ret = void; Args = {char}]’: ./test.cpp:27:10: required from here ./test.cpp:18:8: error: variable or field ‘returnVal’ declared void ./test.cpp:19:11: error: return-statement with a value, in function returning 'void' [-fpermissive]
一つは、通常std::is_void
と組み合わせるstd::enable_if
を使用することになり、問題は、私はに特化したくないということです機能テンプレートが、クラステンプレートにあります。
template <typename Ret, typename... Args>
class Test<Ret (Args...)>
{
public:
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
Ret operator()(Args...)
{
Ret returnVal;
return returnVal;
}
typename std::enable_if<std::is_void<Ret>::value, Ret>::type
Ret operator()(Args...)
{
// It's a void function
// ...
}
};
私が代わりに上記のコードを使用している場合、私はただの馬鹿だ場合、私は申し訳ありませんが、その答えは明白です
./test.cpp:11:2: error: expected ‘;’ at end of member declaration
./test.cpp:11:2: error: declaration of ‘typename std::enable_if<(! std::is_void<_Tp>::value), Ret>::type Test<Ret(Args ...)>::Ret’
./test.cpp:6:11: error: shadows template parm ‘class Ret’
./test.cpp:11:24: error: ISO C++ forbids declaration of ‘operator()’ with no type [-fpermissive]
./test.cpp:18:2: error: expected ‘;’ at end of member declaration
./test.cpp:18:2: error: declaration of ‘typename std::enable_if<std::is_void<_Tp>::value, Ret>::type Test<Ret(Args ...)>::Ret’
./test.cpp:6:11: error: shadows template parm ‘class Ret’
./test.cpp:18:24: error: ISO C++ forbids declaration of ‘operator()’ with no type [-fpermissive]
./test.cpp:18:6: error: ‘int Test<Ret(Args ...)>::operator()(Args ...)’ cannot be overloaded
./test.cpp:11:6: error: with ‘int Test<Ret(Args ...)>::operator()(Args ...)’
./test.cpp: In member function ‘int Test<Ret(Args ...)>::operator()(Args ...)’:
./test.cpp:22:2: warning: no return statement in function returning non-void [-Wreturn-type]
./test.cpp: In instantiation of ‘int Test<Ret(Args ...)>::operator()(Args ...) [with Ret = void; Args = {char}]’:
./test.cpp:28:10: required from here
./test.cpp:13:7: error: variable or field ‘returnVal’ declared void
./test.cpp: In member function ‘int Test<Ret(Args ...)>::operator()(Args ...) [with Ret = void; Args = {char}]’:
./test.cpp:15:2: warning: control reaches end of non-void function [-Wreturn-type]
さらに多くのエラーが発生して、その溶液ずに終わります。私はかなり新しいテンプレートですが、私は他のスレッド/質問のいずれかで適切な答えを見つけることができませんでした。
最初の例で必要としていることを正確に行う「静的なif」を含める提案があります。 – mfontanini
@mfontanini:2つの提案のいずれかが実際に進むかどうかは別の問題です。 –
"静的なテンプレートを使用してSFINAEを使用すると、コンパイラが分岐を削除しないためコンパイラエラーが発生するという問題があります= >残念なことに、コンパイラ*は*ではないことが要求されます。 –