从字符串文字中推导模板参数
Template Argument Deduction from String Literal
我目前正在考虑如何最好地将模板的泛型类型限制为 std::sting
以及字符串文字。因此,我使用 std::is_same
将推导的类型与所需的类型进行比较。在 std::string
的情况下,这会立即起作用。对于字符串字面量,即 char const 数组,只有在类型上使用 std::decay
,然后将结果与类型 char const *
进行比较时,它才有效。如果我直接将推导的类型与我认为应该是的类型进行比较,is_same
returns 错误,如以下示例代码所示。
template <class TYPE>
void function(TYPE&& parameter)
{
//this doesn't work as expected
std::cout << typeid(TYPE).name() << " : " << typeid(char const [5]).name() << std::endl;
std::cout << std::is_same<char const [5], TYPE>::value << std::endl;
//this works as expected
std::cout << typeid(std::decay_t<TYPE>).name() << " : " << typeid(char const *).name() << std::endl;
std::cout << std::is_same<char const *, std::decay_t<TYPE>>::value << std::endl;
}
int main(int argc, char** argv)
{
function("name");
return 0;
}
生成的输出如下:
char const [5] : char const [5]
0
char const * __ptr64 : char const * __ptr64
1
现在,我想知道为什么在第一种情况下 is_same
returns false 即使类型看起来相同。
我能想到的唯一可能的解释是,在函数 std::is_same
中,对类型应用了类似于 std::decay
的转换(例如函数调用)。但是话又说回来,这种转换也会发生在另一种类型上,产生相同的结果,从而导致相等。
使用 gcc 自定义函数:
template < class T >
constexpr std::string type_name()
{
std::string p = __PRETTY_FUNCTION__;
return p.substr( 43 + 10, p.length() - 100 - 1 - 10 );
}
并将其添加到您的代码中:
std::cout << type_name<TYPE>() << " : " << type_name<char const [5]>() << std::endl;
结果是:
A5_c : A5_c
0
const char (&)[5] : const char [5]
因此您需要在 TYPE
上使用 std::remove_reference
。
可能是编译器的错误。编译器在编译时生成由 typeid 给出的此类类型对象。编译器不会为每个长度(0 到 2**n)编译数组类型,因此它会在需要时编译它们,并且它可能 "forget" 关于重复项。尝试使用特殊模板,将长度与包含的类型分开。这不是类型,但您可以检查它是否等于另一个类型。
template<class T, size_t size>
struct array_t{};
template <class T, size_t size>
void function(T[size] parameter) {
std::cout << typeid(array_t<T, size>).name() << " : " << typeid(array_t<char, 5>).name() << std::endl;
std::cout << std::is_same<array_t<T, size>, array_t<char, 5>>::value << std::endl;
};
字符串文字不是按 char const [N]
的值传递,而是 reference 的 char const (&)[N]
.
这对我来说是正确的:
std::cout << std::is_same<char const (&)[5], TYPE>::value << std::endl;
注意here那
1) Refers to a std::type_info
object representing the type type. If type is a reference type, the result refers to a std::type_info
object representing the referenced type.
您可以轻松地验证 is_same
不会像 type_info
一样丢弃引用性,例如通过检查
std::is_same<int&, int>::value == false
这解释了为什么 typeid
名称相同,但您的 is_same
测试仍然失败。
我目前正在考虑如何最好地将模板的泛型类型限制为 std::sting
以及字符串文字。因此,我使用 std::is_same
将推导的类型与所需的类型进行比较。在 std::string
的情况下,这会立即起作用。对于字符串字面量,即 char const 数组,只有在类型上使用 std::decay
,然后将结果与类型 char const *
进行比较时,它才有效。如果我直接将推导的类型与我认为应该是的类型进行比较,is_same
returns 错误,如以下示例代码所示。
template <class TYPE>
void function(TYPE&& parameter)
{
//this doesn't work as expected
std::cout << typeid(TYPE).name() << " : " << typeid(char const [5]).name() << std::endl;
std::cout << std::is_same<char const [5], TYPE>::value << std::endl;
//this works as expected
std::cout << typeid(std::decay_t<TYPE>).name() << " : " << typeid(char const *).name() << std::endl;
std::cout << std::is_same<char const *, std::decay_t<TYPE>>::value << std::endl;
}
int main(int argc, char** argv)
{
function("name");
return 0;
}
生成的输出如下:
char const [5] : char const [5]
0
char const * __ptr64 : char const * __ptr64
1
现在,我想知道为什么在第一种情况下 is_same
returns false 即使类型看起来相同。
我能想到的唯一可能的解释是,在函数 std::is_same
中,对类型应用了类似于 std::decay
的转换(例如函数调用)。但是话又说回来,这种转换也会发生在另一种类型上,产生相同的结果,从而导致相等。
使用 gcc 自定义函数:
template < class T >
constexpr std::string type_name()
{
std::string p = __PRETTY_FUNCTION__;
return p.substr( 43 + 10, p.length() - 100 - 1 - 10 );
}
并将其添加到您的代码中:
std::cout << type_name<TYPE>() << " : " << type_name<char const [5]>() << std::endl;
结果是:
A5_c : A5_c
0
const char (&)[5] : const char [5]
因此您需要在 TYPE
上使用 std::remove_reference
。
可能是编译器的错误。编译器在编译时生成由 typeid 给出的此类类型对象。编译器不会为每个长度(0 到 2**n)编译数组类型,因此它会在需要时编译它们,并且它可能 "forget" 关于重复项。尝试使用特殊模板,将长度与包含的类型分开。这不是类型,但您可以检查它是否等于另一个类型。
template<class T, size_t size>
struct array_t{};
template <class T, size_t size>
void function(T[size] parameter) {
std::cout << typeid(array_t<T, size>).name() << " : " << typeid(array_t<char, 5>).name() << std::endl;
std::cout << std::is_same<array_t<T, size>, array_t<char, 5>>::value << std::endl;
};
字符串文字不是按 char const [N]
的值传递,而是 reference 的 char const (&)[N]
.
这对我来说是正确的:
std::cout << std::is_same<char const (&)[5], TYPE>::value << std::endl;
注意here那
1) Refers to a
std::type_info
object representing the type type. If type is a reference type, the result refers to astd::type_info
object representing the referenced type.
您可以轻松地验证 is_same
不会像 type_info
一样丢弃引用性,例如通过检查
std::is_same<int&, int>::value == false
这解释了为什么 typeid
名称相同,但您的 is_same
测试仍然失败。