英文:
What are the new ways to pass functions as template arguments in C++11?
问题
在问题将函数作为模板参数传递中,提出并解释了在C++中将函数作为模板参数传递的两种传统方式:
- 将函数声明为“函数对象”(例如,具有重载
()
运算符的对象)。但这需要先修改目标函数。 - 使用函数指针作为参数,并使用
&
运算符取函数的地址以使用模板。但这可能会抑制编译器的优化,特别是内联,因为编译器可能无法确定裸指针的目标。
我已阅读并在概念上理解了这两种方法。然而,在答案下用户pfalcon的评论中,他声称:
> 快进到几年后,C++11中使用函数作为模板参数的情况得到了很大改善。你不再受到使用像函数对象类似的Javaisms的限制,可以直接使用静态内联函数作为模板参数。虽然与上世纪70年代的Lisp宏相比仍有很大差距,但C++11在这方面确实取得了很大进展。
但没有提供解释或示例。在C++11中,pfalcon所指的被认为是“改进很多”的方法是什么呢?我尝试搜索“C++11中的函数模板参数”,但没有看到可用的结果。
英文:
In the question Function passed as template argument, it was asked and explained that there are two traditional ways of passing a function as a template argument in C++, they're:
- Declaring the function as a "functor" (e.g. an object with an overridden
()
operator). But it requires modifying the target function first. - Using function pointer as the parameter, and taking the address of the function with the
&
operator to use the template. But this can possibly inhibit compiler optimization, especially inlining, since the compiler may be unable to figure out the target of the naked pointer.
I have read and conceptually understood both methods. However, in a comment by user pfalcon under the answer, it was claimed that:
> Fast forward to few years later, situation with using functions as template arguments much improved in C++11. You no longer bound to use Javaisms like functor classes, and can use for example static inline functions as template arguments directly. Still far cry comparing to Lisp macros of 1970s, but C++11 definitely has good progress over the years.
But no explanation or example is given. What are the supposedly "much improved" ways of doing that in C++11 that pfalcon was referring to? I tried to search "function as template argument C++11" but I didn't see any usable result.
答案1
得分: 3
Up until C++11, it was not possible to use functions with internal linkage as arguments for NTTPs (non-type template parameters). This restriction was lifted in C++11, allowing you to use functions with internal linkage for NTTPs as well. Before, callback
would require external linkage, which is problematic if this code is all written in a source file because other source files containing their own callback
would conflict with our callback
. In C++11, you are still not allowed to use lambda expressions as template arguments, and creating your own callable types is more verbose, so the above code is as concise as it gets.
英文:
Up until C++11, it was not possible to use functions internal linkage as arguments for NTTPs (non-type template parameters). For example, compiling the following code with -std=c++98
fails:
template <void(*fun)()>
void call() {
fun();
}
// removing static is necessary in C++98
static void callback() {}
void foo() {
call<callback>();
}
>
> <source>:9:19: error: 'callback' is not a valid template argument
> | for type 'void > (*)()' because 'void callback()'
> | does not have external linkage
> |
> 9 | call<callback>();
> | ~~~~~~~~~~~~~~^~
>
This is due to this section:
> #### 14.3.2 Template non-type arguments
> 1 A template-argument for a non-type, non-template template-parameter shall be one of:
> - [...]
> - the name of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as id-expression; or
> - [...]
This restriction was lifted in C++11, allowing you to use functions with internal linkage for NTTPs as well. Before, callback
would require external linkage, which is problematic if this code all written in a source file, because other source files containing their own callback
would conflict with our callback
.
In C++11, you are still not allowed to use lambda expressions as template arguments, and creating your own callable types is more verbose, so the above code is as concise as it gets.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论