Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么变量函数不能与模板一起使用_C++_Templates_Variadic Templates_Variadic - Fatal编程技术网

C++ 为什么变量函数不能与模板一起使用

C++ 为什么变量函数不能与模板一起使用,c++,templates,variadic-templates,variadic,C++,Templates,Variadic Templates,Variadic,我想写一个函数来比较几个值,并检查其中哪一个最小。我想把它实现为一个可变函数模板。我知道,自从C++11以来,就有一个用于此目的的特性,但由于种种原因,我目前无法使用它。所以我试着使用库,但偶然发现了一些问题。由于某些原因,当我将函数用作模板时,参数的偏移量计算错误。如果我用固定类型显式地实现函数,我就没有问题 我的代码: #include <cstdarg> #include <iostream> #include <limits> template &

我想写一个函数来比较几个值,并检查其中哪一个最小。我想把它实现为一个可变函数模板。我知道,自从C++11以来,就有一个用于此目的的特性,但由于种种原因,我目前无法使用它。所以我试着使用
库,但偶然发现了一些问题。由于某些原因,当我将函数用作模板时,参数的偏移量计算错误。如果我用固定类型显式地实现函数,我就没有问题

我的代码:

#include <cstdarg>
#include <iostream>
#include <limits>


template <typename T>
T smallestOf(const int count, const T val1, ... ) { /* I use val1 to determine the template type */
    va_list args;
    va_start(args, val1);
    T smallestVal = std::numeric_limits<T>::max();
    for(int i = 0; i < count; i++) {
        T nextVal = va_arg(args, T);
        std::cout << "nextVal: " << nextVal << std::endl;
        if(nextVal < smallestVal) smallestVal = nextVal;
    }
    va_end(args);
    return smallestVal;
}


int main() {
    std::cout << "Smallest value: " << smallestOf(3, 10, 20, 30) << std::endl;
}
这看起来像是函数在偏移错误时读取其内存。为什么呢

T smallestOf(const int count, const T val1, ... )
当您这样调用时:
smallestOf(3,10,20,30)
变量是
20 30
(因为
10
val1
)。所以您需要
计数-1

另外strong建议:不要使用varargs。使用可变模板或
std::initializer\u list

您说您没有访问C++11的权限,所以不幸的是,您既没有访问变量模板,也没有访问初始值设定项列表的权限

好吧,这是我给你的礼物:

template <class T> T min(T e1) { return e1; }
template <class T> T min(T e1, T e2) { return e1 < e2 ? e1: e2; }
template <class T> T min(T e1, T e2, T e3) { return min(e1, min(e2, e3)); }
template <class T> T min(T e1, T e2, T e3, T e4) { return min(e1, min(e2, e3, e4)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5) { return min(e1, min(e2, e3, e4, e5)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6) { return min(e1, min(e2, e3, e4, e5, e6)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6, T e7) { return min(e1, min(e2, e3, e4, e5, e6, e7)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6, T e7, T e8) { return min(e1, min(e2, e3, e4, e5, e6, e7, e8)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6, T e7, T e8, T e9) { return min(e1, min(e2, e3, e4, e5, e6, e7, e8, e9)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6, T e7, T e8, T e9, T e10) { return min(e1, min(e2, e3, e4, e5, e6, e7, e8, e9, e10)); }
template T min(te1){return e1;}
模板tmin(te1,te2){返回e1
您可能会说这是次优的,或者您可以对调用进行分组以减少调用,但是任何合适的编译器都会为您内联并优化所有这些调用。
clang
gcc
都使用10个参数编译
min
,其中仅包含无分支的
mov
cmp
cmov
指令

当您这样调用时:
smallestOf(3,10,20,30)
变量是
20 30
(因为
10
val1
)。所以您需要
计数-1

另外strong建议:不要使用varargs。使用可变模板或
std::initializer\u list

您说您没有访问C++11的权限,所以不幸的是,您既没有访问变量模板,也没有访问初始值设定项列表的权限

好吧,这是我给你的礼物:

template <class T> T min(T e1) { return e1; }
template <class T> T min(T e1, T e2) { return e1 < e2 ? e1: e2; }
template <class T> T min(T e1, T e2, T e3) { return min(e1, min(e2, e3)); }
template <class T> T min(T e1, T e2, T e3, T e4) { return min(e1, min(e2, e3, e4)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5) { return min(e1, min(e2, e3, e4, e5)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6) { return min(e1, min(e2, e3, e4, e5, e6)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6, T e7) { return min(e1, min(e2, e3, e4, e5, e6, e7)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6, T e7, T e8) { return min(e1, min(e2, e3, e4, e5, e6, e7, e8)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6, T e7, T e8, T e9) { return min(e1, min(e2, e3, e4, e5, e6, e7, e8, e9)); }
template <class T> T min(T e1, T e2, T e3, T e4, T e5, T e6, T e7, T e8, T e9, T e10) { return min(e1, min(e2, e3, e4, e5, e6, e7, e8, e9, e10)); }
template T min(te1){return e1;}
模板tmin(te1,te2){返回e1

您可能会说这是次优的,或者您可以对调用进行分组以减少调用,但是任何合适的编译器都会为您内联并优化所有这些调用。
clang
gcc
都使用10个参数编译
min
,其中只有无分支的
mov
cmp
cmov
指令。

刚刚注意到没有可用的c++11,但由于我刚刚编写了它,这里有一个用c++17编写的变量解决方案的示例

也许将来会有用

#include <iostream>
#include <utility>
#include <type_traits>

template<class T, class...Rest>
auto smallestOf(T const& val1, Rest const&...rest) 
-> std::enable_if_t<std::is_same_v<std::common_type_t<T, Rest...>, T>, T const&>
{
    auto* current = std::addressof(val1);

    if constexpr (sizeof...(Rest) > 0)
    {
        auto check = [](T const* x, T const* y)
        {
            return std::addressof(std::min(*x, *y));
        };

        ((current = check(current, std::addressof(rest))),...);
    }    
    return *current;
}

int main() {
    std::cout << "Smallest value: " << smallestOf(10) << std::endl;
    std::cout << "Smallest value: " << smallestOf(20, 10) << std::endl;
    std::cout << "Smallest value: " << smallestOf(30, 10, 20) << std::endl;
    std::cout << "Smallest value: " << smallestOf(30, 10, 40, 20) << std::endl;
}
#包括
#包括
#包括
模板
自动最小值(T常量和值1,Rest常量和…Rest)
->std::如果启用,则启用
{
自动*电流=标准::地址(val1);
如果constexpr(sizeof…(Rest)>0)
{
自动检查=[](T常数*x,T常数*y)
{
返回std::addressof(std::min(*x,*y));
};
((当前=检查(当前,std::addressof(剩余)),…);
}    
返回*当前值;
}
int main(){

std::cout刚刚注意到没有可用的c++11的评论,但是由于我刚刚编写了它,这里有一个用c++17编写的变量解决方案的示例

也许将来会有用

#include <iostream>
#include <utility>
#include <type_traits>

template<class T, class...Rest>
auto smallestOf(T const& val1, Rest const&...rest) 
-> std::enable_if_t<std::is_same_v<std::common_type_t<T, Rest...>, T>, T const&>
{
    auto* current = std::addressof(val1);

    if constexpr (sizeof...(Rest) > 0)
    {
        auto check = [](T const* x, T const* y)
        {
            return std::addressof(std::min(*x, *y));
        };

        ((current = check(current, std::addressof(rest))),...);
    }    
    return *current;
}

int main() {
    std::cout << "Smallest value: " << smallestOf(10) << std::endl;
    std::cout << "Smallest value: " << smallestOf(20, 10) << std::endl;
    std::cout << "Smallest value: " << smallestOf(30, 10, 20) << std::endl;
    std::cout << "Smallest value: " << smallestOf(30, 10, 40, 20) << std::endl;
}
#包括
#包括
#包括
模板
自动最小值(T常量和值1,Rest常量和…Rest)
->std::如果启用,则启用
{
自动*电流=标准::地址(val1);
如果constexpr(sizeof…(Rest)>0)
{
自动检查=[](T常数*x,T常数*y)
{
返回std::addressof(std::min(*x,*y));
};
((当前=检查(当前,std::addressof(剩余)),…);
}    
返回*当前值;
}
int main(){

STD::CUT变量函数实际上是C的左撇子,并且有坏的C++支持。例如,只有第二个参数 Val1将有类型<代码> t>代码>,其他参数的类型不被检查,可以是任何东西。尝试使用它。它也产生错误的输出,无论它是模板,也都是这个特定函数。d可以实现为(可能)在编译时计算的函数。可变函数实际上是