实例化部分模板规范的别名时隐式实例化未定义模板
implicit instantiation of undefined template when instantiating alias of partial template spec
我正在按照“实用 C++ 元编程”一书中的示例模板进行操作,并且已经到达示例的一部分,如果不绕过别名,我将无法编译代码.使用别名 make_tuple_of_derefed_params_t 时,我在定义时收到编译器错误“未定义模板的隐式实例化”。我可以使用部分模板专业化 make_tuple_of_derefed_params 直接调用它,但不能使用别名。还有什么我需要做的吗?我在 clang++ 和 g++ 中都收到错误。
template <typename F>
class make_tuple_of_derefed_params;
template <typename Ret, typename... Args>
struct make_tuple_of_derefed_params<Ret (Args...)>
{
using type = std::tuple<std::remove_pointer_t<Args>...>;
};
template <typename F>
using make_tuple_of_derefed_params_t = typename make_tuple_of_derefed_params<F>::type;
完整代码为:
#include <numeric>
#include <iostream>
#include <type_traits>
#include <tuple>
#include <utility>
#include <time.h>
void adjust_values(double * alpha1,double * beta1,double * alpha2,double * beta2) { }
struct location {
int x;
int y;
};
class reading
{
/* stuff */
public:
double alpha_value(location l, time_t t) const { return 1.5; }
double beta_value(location l, time_t t) const { return 2.5; }
/* other stuff */
};
template <typename F>
class make_tuple_of_derefed_params;
template <typename Ret, typename... Args>
struct make_tuple_of_derefed_params<Ret (Args...)>
{
using type = std::tuple<std::remove_pointer_t<Args>...>;
};
template <typename F>
using make_tuple_of_derefed_params_t = typename make_tuple_of_derefed_params<F>::type;
template <std::size_t FunctionIndex,typename FunctionsTuple,
typename Params, std::size_t... I>
auto dispatch_params(FunctionsTuple & functions,Params & params,
std::index_sequence<I...>)
{
return (std::get<FunctionIndex>(functions))(std::get<I>(params)...);
}
template <typename FunctionsTuple, std::size_t... I, typename Params,
typename ParamsSeq>
auto dispatch_functions(FunctionsTuple & functions,
std::index_sequence<I...>, Params & params,
ParamsSeq params_seq)
{
return std::make_tuple(dispatch_params<I>(functions,params,params_seq)...);
}
template <typename LegacyFunction,typename... Functions,typename... Params>
auto magic_wand(
LegacyFunction legacy,
const std::tuple<Functions...> & functions,
const std::tuple<Params...> & params1,
const std::tuple<Params...> & params2)
{
static const std::size_t functions_count = sizeof...(Functions);
static const std::size_t params_count = sizeof...(Params);
make_tuple_of_derefed_params_t<LegacyFunction> params =
std::tuple_cat(
dispatch_functions(functions,
std::make_index_sequence<functions_count>(),
params1,
std::make_index_sequence<params_count>()),
dispatch_functions(functions,
std::make_index_sequence<functions_count>(),
params2,
std::make_index_sequence<params_count>()));
/* rest of the code */
static constexpr auto t_count =
std::tuple_size<decltype(params)>::value;
dispatch_to_c( legacy,
params,std::make_index_sequence<t_count>());
return params;
}
template <typename Reading>
std::tuple<double, double, double, double>
get_adjusted_values(Reading & r,
location l,
time_t t1,
time_t t2)
{
return magic_wand(adjust_values,
std::make_tuple(
[&r](location l, time_t t)
{
return r.alpha_value(l, t);
},
[&r](location l, time_t t)
{
return r.beta_value(l, t);
}),
std::make_tuple(l, t1),
std::make_tuple(l, t2)
);
}
int main()
{
reading r;
location l { 1,2 };
time_t epoch = 0;
time_t seconds = time(NULL);
std::tuple<double, double, double, double> ret2 =
get_adjusted_values(r, l, epoch, seconds);
return 0;
}
给定
template <typename T> void f(T);
void g();
三个调用f<void()>(g)
、f<void(*)()>(g)
和f<void(&)()>(g)
都有效。真的,f(g)
可能是其中任何一个。但是标准不得不强制一个,最后变成了f<void(*)()>(g)
。这意味着当您随后将 T
传递给另一个模板时,要么该其他模板需要能够处理指向函数的指针类型,要么您需要将指向函数的指针类型转换为函数类型。
这就是您的 return magic_wand(adjust_values, ...)
通话中发生的情况。
make_tuple_of_derefed_params
仅为函数类型定义。
template <typename F>
class make_tuple_of_derefed_params;
// Definition here, note that it only defines type for "T(Ts...)" template parameters.
template <typename Ret, typename... Args>
struct make_tuple_of_derefed_params<Ret (Args...)>
{
using type = std::tuple<std::remove_pointer_t<Args>...>;
};
template <typename F>
using make_tuple_of_derefed_params_t = typename make_tuple_of_derefed_params<F>::type;
// ...
//make_tuple_of_derefed_params_t<int> foo; // Error if uncommented.
make_tuple_of_derefed_params_t<int(int)> bar; // Works.
//make_tuple_of_derefed_params_t<int(*)(int)> baz; // Error if uncommented.
要解决此问题,您需要为任何其他有效的 F
提供定义。在这种特殊情况下,您需要为何时 F
是函数指针提供定义。
template <typename Ret, typename... Args>
struct make_tuple_of_derefed_params<Ret (*)(Args...)>
{
using type = std::tuple<std::remove_pointer_t<Args>...>;
};
我正在按照“实用 C++ 元编程”一书中的示例模板进行操作,并且已经到达示例的一部分,如果不绕过别名,我将无法编译代码.使用别名 make_tuple_of_derefed_params_t 时,我在定义时收到编译器错误“未定义模板的隐式实例化”。我可以使用部分模板专业化 make_tuple_of_derefed_params 直接调用它,但不能使用别名。还有什么我需要做的吗?我在 clang++ 和 g++ 中都收到错误。
template <typename F>
class make_tuple_of_derefed_params;
template <typename Ret, typename... Args>
struct make_tuple_of_derefed_params<Ret (Args...)>
{
using type = std::tuple<std::remove_pointer_t<Args>...>;
};
template <typename F>
using make_tuple_of_derefed_params_t = typename make_tuple_of_derefed_params<F>::type;
完整代码为:
#include <numeric>
#include <iostream>
#include <type_traits>
#include <tuple>
#include <utility>
#include <time.h>
void adjust_values(double * alpha1,double * beta1,double * alpha2,double * beta2) { }
struct location {
int x;
int y;
};
class reading
{
/* stuff */
public:
double alpha_value(location l, time_t t) const { return 1.5; }
double beta_value(location l, time_t t) const { return 2.5; }
/* other stuff */
};
template <typename F>
class make_tuple_of_derefed_params;
template <typename Ret, typename... Args>
struct make_tuple_of_derefed_params<Ret (Args...)>
{
using type = std::tuple<std::remove_pointer_t<Args>...>;
};
template <typename F>
using make_tuple_of_derefed_params_t = typename make_tuple_of_derefed_params<F>::type;
template <std::size_t FunctionIndex,typename FunctionsTuple,
typename Params, std::size_t... I>
auto dispatch_params(FunctionsTuple & functions,Params & params,
std::index_sequence<I...>)
{
return (std::get<FunctionIndex>(functions))(std::get<I>(params)...);
}
template <typename FunctionsTuple, std::size_t... I, typename Params,
typename ParamsSeq>
auto dispatch_functions(FunctionsTuple & functions,
std::index_sequence<I...>, Params & params,
ParamsSeq params_seq)
{
return std::make_tuple(dispatch_params<I>(functions,params,params_seq)...);
}
template <typename LegacyFunction,typename... Functions,typename... Params>
auto magic_wand(
LegacyFunction legacy,
const std::tuple<Functions...> & functions,
const std::tuple<Params...> & params1,
const std::tuple<Params...> & params2)
{
static const std::size_t functions_count = sizeof...(Functions);
static const std::size_t params_count = sizeof...(Params);
make_tuple_of_derefed_params_t<LegacyFunction> params =
std::tuple_cat(
dispatch_functions(functions,
std::make_index_sequence<functions_count>(),
params1,
std::make_index_sequence<params_count>()),
dispatch_functions(functions,
std::make_index_sequence<functions_count>(),
params2,
std::make_index_sequence<params_count>()));
/* rest of the code */
static constexpr auto t_count =
std::tuple_size<decltype(params)>::value;
dispatch_to_c( legacy,
params,std::make_index_sequence<t_count>());
return params;
}
template <typename Reading>
std::tuple<double, double, double, double>
get_adjusted_values(Reading & r,
location l,
time_t t1,
time_t t2)
{
return magic_wand(adjust_values,
std::make_tuple(
[&r](location l, time_t t)
{
return r.alpha_value(l, t);
},
[&r](location l, time_t t)
{
return r.beta_value(l, t);
}),
std::make_tuple(l, t1),
std::make_tuple(l, t2)
);
}
int main()
{
reading r;
location l { 1,2 };
time_t epoch = 0;
time_t seconds = time(NULL);
std::tuple<double, double, double, double> ret2 =
get_adjusted_values(r, l, epoch, seconds);
return 0;
}
给定
template <typename T> void f(T);
void g();
三个调用f<void()>(g)
、f<void(*)()>(g)
和f<void(&)()>(g)
都有效。真的,f(g)
可能是其中任何一个。但是标准不得不强制一个,最后变成了f<void(*)()>(g)
。这意味着当您随后将 T
传递给另一个模板时,要么该其他模板需要能够处理指向函数的指针类型,要么您需要将指向函数的指针类型转换为函数类型。
这就是您的 return magic_wand(adjust_values, ...)
通话中发生的情况。
make_tuple_of_derefed_params
仅为函数类型定义。
template <typename F>
class make_tuple_of_derefed_params;
// Definition here, note that it only defines type for "T(Ts...)" template parameters.
template <typename Ret, typename... Args>
struct make_tuple_of_derefed_params<Ret (Args...)>
{
using type = std::tuple<std::remove_pointer_t<Args>...>;
};
template <typename F>
using make_tuple_of_derefed_params_t = typename make_tuple_of_derefed_params<F>::type;
// ...
//make_tuple_of_derefed_params_t<int> foo; // Error if uncommented.
make_tuple_of_derefed_params_t<int(int)> bar; // Works.
//make_tuple_of_derefed_params_t<int(*)(int)> baz; // Error if uncommented.
要解决此问题,您需要为任何其他有效的 F
提供定义。在这种特殊情况下,您需要为何时 F
是函数指针提供定义。
template <typename Ret, typename... Args>
struct make_tuple_of_derefed_params<Ret (*)(Args...)>
{
using type = std::tuple<std::remove_pointer_t<Args>...>;
};