我无法理解模板实例化的顺序。如果定义“为时已晚”,编译器似乎不会考虑该函数。以下步骤说明了以下代码的主要思想:
convert<From, To>
如果框架可以找到该函数的工作重载,则该框架应该提供一个自由函数generate
。该函数
to<T>
是一个快捷方式,convert<From,To>
并且仅在有效时才convert<From,To>
有效。用户应该能够提供重载
generate
并能够使用to
andconvert
。
对应代码:
#include <string>
#include <utility>
#include <iostream>
// If I move the code down below at [*] to this location, everything works as
// expected.
// ------------- Framework Code -------------
// Anything that can be generated can also be converted to a string.
template <typename From>
auto convert(From const& from, std::string& to)
-> decltype(
generate(std::declval<std::back_insert_iterator<std::string>&>(), from)
)
{
to.clear();
auto i = std::back_inserter(to);
return generate(i, from);
}
// Similar to convert, except that it directly returns the requested type.
template <typename To, typename From>
auto to(From const& f) -> decltype(convert(f, std::declval<To&>()), To())
{
To t;
if (! convert(f, t))
throw std::invalid_argument("invalid conversion");
return t;
}
// ------------- User Code -------------
// [*] Support arithmetic types.
template <typename Iterator, typename T>
auto generate(Iterator& out, T i)
-> typename std::enable_if<std::is_arithmetic<T>::value, bool>::type
{
// Note: I merely use std::to_string for illustration purposes here.
auto str = std::to_string(i);
out = std::copy(str.begin(), str.end(), out);
return true;
}
int main()
{
uint16_t s = 16;
std::cout << to<std::string>(s) << std::endl;
return 0;
}
以下代码中的问题是,它仅在函数generate
出现在convert
and的定义之前才有效to
。我该如何解决这个问题?
也许我的心智模型在这里是错误的,但我认为当编译器看到模板时to<std::string>(uint16_t)
,它会开始倒退并根据需要进行实例化。任何指导将不胜感激。