标签: function-templates

在 C++20 中实现可变参数 Max 函数

尽管如此,事实上,我们有std::max,我想尝试是否可以制作一个Max采用可变参数并递归调用Max 以查找最大元素的版本。

我在堆栈溢出中看到了类似的帖子,但这些帖子已经很旧了,而且大多数都std::max在内部使用。由于我有一个特定的错误并使用较新的编译器,因此这篇文章不容易重复。

以下是我写的代码:

#include <iostream>
#include <string>
#include <format>
using namespace std::string_literals;

template <typename T>
constexpr T Max(T&& value)
{  
  return value;
}

template <typename T, typename... Ts>
constexpr T Max(T&& value, Ts&&... args)
{
    const T maxRest = Max(args...);

    return (value > maxRest) ? value : maxRest;
}

int main()
{
    std::cout << std::format("Maximum integer: {}\n", Max(1));
    std::cout << std::format("Maximum integer: {}\n", Max(5, 2, 10, 6, 8));
    std::cout << std::format("Maximum integer: …
Run Code Online (Sandbox Code Playgroud)

c++ templates function-templates variadic-templates c++20

9
推荐指数
1
解决办法
278
查看次数

功能模板的部分特化

在下面的代码段中,

template<typename T1>
void func(T1& t)
{
    cout << "all" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "float" << endl;
}

// I do not want this
// template<> void func(float &t)

int main()
{
    int i; float f;
    func(i); // should print "all"
    func(f); // should print "float" 
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望修改模板,通过传递浮动以外的任何类型将打印"all"并传递float将打印"float".我不想要模板特化,而是根据输入类型进行相应的部分特化.我应该怎么做呢.提前致谢.

那个场景,我现在面临的是,我需要定义以下内容,

template<typename T1>
void func(T1 &t)
{
    cout << "t1" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "t2" << …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-specialization function-templates

8
推荐指数
3
解决办法
7156
查看次数

类模板的朋友功能

我有一个课程模板Foo<T>.

我想实现一个非成员函数Bar,它需要两个Foos并返回一个Foo.我想Bar成为一名非会员,因为写作者Bar(f1, f2)比写作更自然f1.Bar(f2).我也想Bar成为inline因为计算是微不足道的.

template <typename T>
inline Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

诀窍是Bar需要访问Foo私人数据.我不希望拥有私有数据的访问者 - 没有充分的理由将私有数据暴露给用户.所以我想结交Bar一个朋友Foo.

template <typename T>
class Foo {
  ...
  private:
    T w, x, y, z;
    friend Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs);
};
Run Code Online (Sandbox Code Playgroud)

这是我遇到麻烦的地方.编译器抱怨:

当友元声明引用功能模板的特化时,不能使用内联说明符.

这个规则是由标准强加的还是特定于MSVC++?

这是我尝试过的:

  • 创建Bar一个const公共成员函数,然后声明一个简单返回的非成员版本lhs.Bar(rhs).这似乎是最不讨厌的解决方案.

  • 删除inline提示,知道编译器将决定内联而不管提示.这是否会违反单一定义规则?它仍然必须在头文件中定义,因为它是一个函数模板. …

c++ friend function-templates non-member-functions

8
推荐指数
1
解决办法
2498
查看次数

指向函数和ODR的指针

关于ODR有很多问题,但是我找不到我要找的东西,所以如果这个副本或标题不合适就道歉.

考虑以下:

struct t {t(*id)();};

template<typename T>
t type() {return {type<T>};}
Run Code Online (Sandbox Code Playgroud)

这是我对每种类型定义唯一标识符的过度简化,希望在不同的编译单元中保持唯一.

特别地,给定一个具体的类型Tstd::string,并且假定两个不同的编译单元包括在头文件上面的代码,我想表达

type<T>().id
Run Code Online (Sandbox Code Playgroud)

t(*)()在两个单元中采用相同的值(类型),因此用作类型的唯一标识符T.

该值是函数的地址type<T>,所以问题是一个独特的功能,type<T>程序被保证一个定义规则.iso 3.2/3说

每个程序应该只包含该程序中使用的每个非内联函数或变量的一个定义.

其中3.2/2

一个非重载函数,其名称显示为可能被评估的表达式或[...],使用的是odr,除非[...]

我假设一个函数是非内联的,如果它的地址被采用(虽然我在标准中找不到).

iso 3.2/5列出了许多例外,但对函数的唯一引用是

带有外部链接的内联函数,[...],非静态函数模板,类模板的成员函数,或者未指定某些模板参数的模板特化[...]

似乎没有一个在这里的情况.

一个可验证的示例将需要多个文件.事实上,DieterLücking给出了一个声称失败的例子,虽然它在我的情况下并没有失败(我没有采取任何形式的"保证").

那么,这是否有效?

c++ function-pointers one-definition-rule function-templates c++11

8
推荐指数
1
解决办法
382
查看次数

为什么我不能在std :: transform中使用std :: get <0>?

在尝试编译以下代码时,会将maps键复制到vector:

map<string, string> mss;
vector<string> vs;

transform(mss.begin(), mss.end(), back_inserter(vs), get<0>);
Run Code Online (Sandbox Code Playgroud)

VS2013无法区分哪个get是预期的,但这个更简单的用法可以正常工作:

vs.push_back(get<0>(*mss.begin()));
Run Code Online (Sandbox Code Playgroud)

指定get<0, string, string>没有帮助.我错过了什么?

c++ function-templates overload-resolution c++11

8
推荐指数
2
解决办法
876
查看次数

将(部分)模板化模板函数作为std :: function(或函数指针)传递

#include <vector>
#include <functional>

template<class F>
class Foo
{
public:
    template <class T>
    void std_function(std::function<F(std::vector<T>)> functor)
    {
        /* something */
    }

    template <class T>
    void func_ptr(F (*funtor)(std::vector<T>))
    {
        /* something else */
    }
};

template<class T, class F>
F bar(std::vector<T>)
{
    return F();
}

int main()
{
    Foo<double> test;
    std::function<double(std::vector<int>)> barz = bar<int, double>;

    test.std_function(bar<int, double>); //error 1
    test.std_function(barz); //OK 1
    test.func_ptr(bar<int, double>); //OK 2

    test.std_function(bar<int>); //error 2::1
    test.func_ptr(bar<int>); //error 2::2

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题1.

错误1:我试图将显式实例化的模板函数(bar<int, double> …

c++ templates function-templates c++11 c++14

8
推荐指数
1
解决办法
627
查看次数

为什么uninitialized_copy中需要voidify函数模板

我正在阅读std::uninitialized_copy并发现了一个叫做voidify

效果: 相当于:

for (; first != last; ++result, (void) ++first)
//#1----vvvvvvv----------->what does this call to voidify mean here
 ::new (voidify(*result))
   typename iterator_traits<NoThrowForwardIterator>::value_type(*first);
Run Code Online (Sandbox Code Playgroud)

经过进一步查找voidify,我发现它是一个函数模板:

本节中指定的一些算法使用仅说明函数 voidify:

template<class T>
 constexpr void* voidify(T& obj) noexcept {
//#2------vvvvvvvvvv-------------------------------->why does this const_cast to void* is needed
   return const_cast<void*>(static_cast<const volatile void*>(addressof(obj)));
//#3------------------------^^^^^^^^^^^------------->why this static_cast to const volatile void* is needed
 }
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,它voidify返回了void*toobj或其他我不太明白的东西,因为涉及到一些强制转换,我不知道为什么需要它们。我已发表评论表明我的疑问。有人可以逐步告诉我为什么voidify需要new (voidify(*result))以及为什么const_cast需要static_cast

总之(只是为了清楚地表达我的疑问)我的问题是:

  1. 为什么我们需要打电话 …

c++ templates function-templates

8
推荐指数
1
解决办法
417
查看次数

关于模板中的通用初始化的C++

我正在编写如下的通用函数.

template<class Iterator, class T>
void foo(Iterator first, Iterator last) {
   T a;
   cout << a << endl;
   // do something with iterators
 }

 typedef vector<double>::iterator DblPtr;
 vector<double> values;
 foo< DblPtr, int>();
Run Code Online (Sandbox Code Playgroud)

a如果我将初始化更改为,则此函数会打印出变量的未定义值

   ///
   T a = T()
   cout << a << endl;
   // do something with iterators
Run Code Online (Sandbox Code Playgroud)

我可以看到初始值是0我所期待的.

如果我调用T a变量初始化为默认值,但如果我调用T a = T()我相信由于优化,应该调用复制构造函数,其值T()仍然是默认值.

我无法理解这两条线背后的区别是什么以及这种情况发生的原因?

c++ templates initialization generic-programming function-templates

7
推荐指数
1
解决办法
923
查看次数

链接器错误:使用外部变量的函数模板中的未定义引用

我有一个包含两个文件的小项目:

主程序

#include <string>
template<int I>
int getint(int i)
{
    extern std::string var;
    return var.size() * i;
}

int main()
{
    return getint<2>(2);
}
Run Code Online (Sandbox Code Playgroud)

和子.cpp

#include <string>
extern std::string var;
std::string var = "Hello";
Run Code Online (Sandbox Code Playgroud)

但是当我编译项目时,链接器给出了错误:

-------------- Clean: Debug in test (compiler: GNU GCC Compiler)---------------

Cleaned "test - Debug"

-------------- Build: Debug in test (compiler: GNU GCC Compiler)---------------

mingw32-g++.exe -Wall -fexceptions -g  -c C:\Users\Fan\Downloads\test\test\main.cpp -o obj\Debug\main.o
mingw32-g++.exe -Wall -fexceptions -g  -c C:\Users\Fan\Downloads\test\test\sub.cpp -o obj\Debug\sub.o
mingw32-g++.exe  -o bin\Debug\test.exe obj\Debug\main.o obj\Debug\sub.o   
obj\Debug\main.o: In …
Run Code Online (Sandbox Code Playgroud)

c++ linker-errors unresolved-external function-templates

7
推荐指数
0
解决办法
185
查看次数

在没有 lambda 的情况下将模板化函数作为方法参数传递?

我确实希望能够在不声明 lambda 的情况下使用 extFunction or std::maxorstd::min作为 square 方法的参数:

template<typename T>
T extFunction(T a, T b)
{
    return a;
}

class Stuff
{
public:
    template <typename F>
    int square(int num, int num2, F&& func) 
    {
        return func(num, num2);
    }
};

int main()
{
    Stuff s;
    std::cout << s.square(1, 2, std::max<int>) << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是编译器(gcc 11.1)告诉我:

函数不明确:“无法推导出模板参数‘ F’”

没有 lambdas 有没有一种简单的方法可以做到这一点?

编辑:

也许展示如何使用 lambdas 做到这一点会很有趣:

std::cout << s.square(1,2,[](auto&& a, auto&& b){return std::max(a,b);}) << std::endl; …
Run Code Online (Sandbox Code Playgroud)

c++ lambda templates function-pointers function-templates

7
推荐指数
1
解决办法
268
查看次数