【发布时间】:2019-01-03 07:45:17
【问题描述】:
抱歉代码不重要(也在 wandbox here 上)
#include <memory>
#include <cstdio>
template< typename T, size_t N, typename ... Args >
void test_1 ( Args ... args)
{
using namespace std;
if constexpr( 1 > (sizeof... (args)) ) {
return;
}
else
{
auto arg_list [[maybe_unused]] = { args ... };
}
}
template< typename T, size_t N, typename ... Args >
void test_2 ( Args ... args)
{
auto arg_list [[maybe_unused]] = { args ... };
}
///////////////////////////////////////////////////////////
int main()
{
test_1<int,3>(1,2,3);
test_2<int,3>(1,2,3);
// taking the function pointer (aka address of) leads to
// full instantiation of function template
constexpr auto adr_1 [[maybe_unused]] = std::addressof(test_1<int,3>);
// no can do --> constexpr auto adr_2 = std::addressof(test_2<int,3>);
}
所以。从上面可以看出,获取模板函数指针(也称为地址)会导致函数模板的完整实例化。
这有点不幸。如果一个人使用模板函数实例化的地址,那将产生一个完整的实例化。即使那个永远不会被调用。
// pointer to instance made but instance never used
constexpr auto adr_5 [[maybe_unused]] = std::addressof(test_1<float,9>);
// pointer to instance made but instance never used
constexpr auto adr_of_big_foot_gun
[[maybe_unused]] = std::addressof(test_1<bool,99>);
// pointer to instance made but instance never used
constexpr auto adr_of_crazy [[maybe_unused]] =
std::addressof(test_1<char, 0xFFFF>);
现在。如何避免这种情况?请注意上面的代码意味着编译器会这样做:
// this line
std::addressof( test_2<int,3> )
// provokes something like this
// which needs to be compiled
test_2<int,3>(void) ;
这就是为什么可以取上面test1的地址,但不能取test_2的原因。也许对我来说,这根本没有任何意义。通过这个,我的具体意思是编译函数模板实例,就好像通过使用 void 参数调用它一样?这反过来意味着,如果没有constexpr-if,将很难在上面写 test_1。这反过来(几乎)意味着没有 c++11 也没有 c++14。
请讨论...
【问题讨论】:
-
没有办法绕过这个。某些东西需要存在才能有地址。您究竟希望您的未实例化函数模板特化的地址是什么?
-
那么,你想避免实例化,但是你期望什么指针值呢?你只需要函数类型吗?
-
您是否尝试进行诸如“函数在调用函数指针时实例化”之类的优化?如果是这样,这是不可能的,因为 c++ 仅在编译时执行此技巧。如果您对
adr_1 == nullptr没问题,那么只需typedef您的函数指针类型并将其分配给nullptr。 -
是的,这正是一个相当不错的东西。在编译器中。
-
注意
std::addressof( test_1<int,3> ) != std::addressof( test_1<int,3, char> ),所以无效test_2<int,3>的地址无论如何都没用。
标签: c++ function templates pointers