英文:
Templated function with optional compile time arg
问题
以下是翻译好的部分:
我有以下带有可选 port
参数的模板函数,应在编译时识别:
template<typename T>
void inner(T arg1){...}
template<typename T>
void inner(T arg1, int port){...}
我想要从外部函数中以最少的重复调用内部函数:
template<typename T>
void outer(T arg1){
/* 做一些操作 */
inner(arg1);
}
template<typename T>
void outer(T arg1, int port){
/* 做与 void outer(T arg1) 中相同的操作 */
inner(arg1, port);
}
在我的解决尝试中,我使用了可变参数模板:
template<typename T, typename... Args>
void outer(T arg1, Args... args){
inner(arg1, args...);
}
它的用法如下:
int main(int argc, char **argv)
{
outer(10);
outer(10, 20);
return 0;
}
然而,我不喜欢有可变数量的参数,只想要0个或1个。
要么你指定 port
,要么不指定。
我该如何做到这一点?
尝试过探索 SFINAE
、enable_if
等,但我无法理解它们。
英文:
I have the following templated functions with an optional port
argument, which should be recognized at compile time:
template<typename T>
void inner(T arg1){...}
template<typename T>
void inner(T arg1, int port){...}
I want to call the inner functions from outer functions with minimum repetition:
template<typename T>
void outer(T arg1){
/* Do some stuff */
inner(arg1);
}
template<typename T>
void outer(T arg1, int port){
/* Do same stuff as in void outer(T arg1) */
inner(arg1, port);
}
In my solution attempt I made use of variadic templates:
template<typename T, typename... Args>
void outer(T arg1, Args... args){
inner(arg1, args...);
}
It is used like this:
int main(int argc, char **argv)
{
outer(10);
outer(10, 20);
return 0;
}
However, I do not like to have a variable amount of parameters but just 0 or 1.
Either you specify the port or not.
How can I do this?
Tried to explore SFINAE
, enable_if
and such, but I was not able to make sense out of it.
答案1
得分: 3
以下是翻译好的部分:
通常避免重复的方式是编写一个函数:
void Do_some_stuff(Some args);
template<typename T>
void outer(T arg1){
Do_some_stuff( ... );
inner(arg1);
}
template<typename T>
void outer(T arg1, int port){
Do_some_stuff( ... );
inner(arg1, port);
}
英文:
The usual way to avoid repetition is to write a function:
void Do_some_stuff(Some args);
template<typename T>
void outer(T arg1){
Do_some_stuff( ... );
inner(arg1);
}
template<typename T>
void outer(T arg1, int port){
Do_some_stuff( ... );
inner(arg1, port);
}
答案2
得分: 1
有多种选择可供考虑。最简单的方法是使用可变模板,但在外部函数中限制参数数量,例如使用 static_assert:
#include<iostream>
template<typename T>
void inner(T arg1){std::cout << "one\n";}
template<typename T>
void inner(T arg1, int port){std::cout << "two\n";}
template<typename T, typename... Args>
void outer(T arg1, Args... args){
static_assert(sizeof...(Args) < 2, "no more than one param");
inner(arg1, args...);
}
int main()
{
outer(1,2);
outer(1);
// outer(1,2,3); //fails to compile
}
如果第二个参数的类型已知,outer
可以是一个单独的函数,接受两个参数,其中一个默认为空的可选项。我无法确定这是否符合您的 API 和 ABI 的要求,但如果可以的话,代码如下:
#include <iostream>
#include <optional>
template<typename T>
void inner(T arg1){std::cout << "one\n";}
template<typename T>
void inner(T arg1, int port){std::cout << "two\n";}
template<typename T>
void outer(T arg1, std::optional<int> port = {} ){
if (port) {
inner(arg1, *port);
} else {
inner(arg1);
}
}
int main()
{
outer(1,2);
outer(1);
// outer(1,2,3); //fails to compile
}
出于示例的目的,我假设您正在使用 C++17 或更新版本,如果不是,则可以将 std::optional
替换为 Boost 中的版本。
英文:
There are multiple options to consider. The easiest one is using a variadic template but limiting the number of arguments in the outer function, e.g. using static_assert
#include<iostream>
template<typename T>
void inner(T arg1){std::cout << "one\n";}
template<typename T>
void inner(T arg1, int port){std::cout << "two\n";}
template<typename T, typename... Args>
void outer(T arg1, Args... args){
static_assert(sizeof...(Args) < 2, "no more than one param");
inner(arg1, args...);
}
int main()
{
outer(1,2);
outer(1);
// outer(1,2,3); //fails to compile
}
https://godbolt.org/z/ehcej8zrs
Given the type of the second parameter is known, outer
can be a single function taking two parameters, one of which is an optional empty by default. I cannot tell if it's acceptable from your API and ABI's standpoint, if it is though, it looks more-less the following way:
#include <iostream>
#include <optional>
template<typename T>
void inner(T arg1){std::cout << "one\n";}
template<typename T>
void inner(T arg1, int port){std::cout << "two\n";}
template<typename T>
void outer(T arg1, std::optional<int> port = {} ){
if (port) {
inner(arg1, *port);
} else {
inner(arg1);
}
}
int main()
{
outer(1,2);
outer(1);
// outer(1,2,3); //fails to compile
}
https://godbolt.org/z/6jnnMMGKW
For the sake of the example I have assumed you are using C++17 or newer, if not, std::optional
can be replaced by the one from Boost.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论