:しかし、私はすでにBoost.PPでそれを実装するためにオフに行っていた、すっごく...
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/comma_if.hpp>
#define DECL_PARAM(r, data, i, elem) \
BOOST_PP_COMMA_IF(i) elem _ ## i
#define FWD_PARAM(r, data, i, elem) \
BOOST_PP_COMMA_IF(i) _ ## i
#define DEF_FN_WRAPPER(name, delegate, params) \
void name(BOOST_PP_SEQ_FOR_EACH_I(DECL_PARAM, ~, params)) { \
delegate(BOOST_PP_SEQ_FOR_EACH_I(FWD_PARAM, ~, params)); \
}
はに展開されます。
最小限、実施例以下の:最後invokationは<int, int, int>
のためにあなたのコンパイル時のエラーを与えるだろう
void _f(int, ...) {}
template<typename...> struct accepts;
template<> struct accepts<int, double, char> {};
template<> struct accepts<int, char, int> {};
template <class... T>
auto f(T... args) -> decltype(accepts<T...>{}, void()) {
_f(args...);
}
int main() {
f(0, 0., 'c');
f(0, 'c', 0);
// f(0, 0, 0);
}
は、構造体accepts
の有効専門ではありません。
これは、プライマリテンプレートが定義されておらず、必要に応じてより多くのスペシャライゼーションを導入して受け入れられたリストを制御できるためです。ここ
はstd::true_type
、std::false_type
とstatic_assert
に基づいてわずかに異なる解決策である。
#include<type_traits>
void _f(int, ...) {}
template<typename...> struct accepts: std::false_type {};
template<> struct accepts<int, double, char>: std::true_type {};
template<> struct accepts<int, char, int>: std::true_type {};
template <class... T>
void f(T... args) {
static_assert(accepts<T...>::value, "!");
_f(args...);
}
int main() {
f(0, 0., 'c');
f(0, 'c', 0);
// f(0, 0, 0);
}
利点がある:
- コンパイル時に、より意味のあるエラーメッセージ(ウェル、もし
"!"
を意味のあるものに置き換えます)
- 可能性t o
std::false_type
から継承して明示的にパラメータリストを無効にし、必要に応じて同時に文書化する。
不利な点は、もう少し冗長であることである。
Oh ... '_f'は古いスタイルのテンプレートではない可変長関数です。 '...'は簡潔さのために省略したものを表すだけではなく、実際はC++の特別な機能です。ええ、私の答えは本当にうまくいかないので、私はそれを削除しました。とにかくありがとう。 – hvd
あまりにも正確ではなかったようです。 –
@hvd私はあなたの答えを得て、それを少し使いました。多分それは今働きます。 – skypjack