gpt4 book ai didi

c++ - 顺序独立的可变参数模板基础特化

转载 作者:行者123 更新时间:2023-11-28 04:55:45 30 4
gpt4 key购买 nike

在 GCC/Clang 上以下代码无法编译:

#include <iostream>
#include <type_traits>
using namespace std;

template<typename X, typename T, typename ...Ts>
void v(X& x, T& value, Ts&... args)
{
v(x, value);
v(x, args...);
}

template<typename X, typename T>
enable_if_t<is_integral_v<T>>
v(X& x, T& value) {
cout << value << endl;
}

template<typename X, typename T>
enable_if_t<is_floating_point_v<T>>
v(X& x, T& value) {
cout << value << endl;
}

int main() {
float f = 5.5;
int i = 2;
v(f, i, i);
}

报错:

> prog.cc: In instantiation of 'void v(X&, T&, Ts& ...) [with X = float; T = int; Ts = {}]':
> prog.cc:8:3: required from 'void v(X&, T&, Ts& ...) [with X = float; T = int; Ts = {int}]'
> prog.cc:27:14: required from here
> prog.cc:9:3: error: no matching function for call to 'v(float&)'
> v(x, args...);
> ~^~~~~~~~~~~~
> prog.cc:6:6: note: candidate: template<class X, class T, class ... Ts> void v(X&, T&, Ts& ...)
> void v(X& x, T& value, Ts&... args)
> ^
> prog.cc:6:6: note: template argument deduction/substitution failed:
> prog.cc:9:3: note: candidate expects at least 2 arguments, 1 provided
> v(x, args...);
> ~^~~~~~~~~~~~

如果在定义了所有基本函数特化之后定义了可变参数函数,则代码可以编译,但是随后您会遇到这种非常不受欢迎的约束,它会导致代码中断,因为您以错误的顺序包含了一些东西。

有没有办法以不依赖于定义顺序的方式向可变参数基函数添加特化?

最佳答案

我发现您的代码中存在一些问题。

首先也是最重要的:你给做两个完全不同的事情的函数赋予相同的名字(v());第一个 v() 在第一个参数上调用打印函数,并递归地调用自身以获取后续参数。其他 v() 正在打印(选择 SFINAE)函数。

建议:使用不同的名称;在下面的示例中,我将 foo() 用于递归函数,将 bar() 用于打印函数。

第二个:您的第一个参数 (X & x) 未被使用。

建议:删除它。

第三:您的函数正在接收非 const 引用,但它们不会修改值。

建议:将参数作为 const 引用接收;所以你也可以调用 v(5.5f, 3L) (你不能用非 const 引用这样调用)

按照这个建议,你的打印功能变成了

template <typename T>
std::enable_if_t<std::is_integral<T>{}> bar (T const & value)
{ std::cout << "integral case: " << value << std::endl; }

template <typename T>
std::enable_if_t<std::is_floating_point<T>{}> bar (T const & value)
{ std::cout << "floating case: " << value << std::endl; }

和递归函数(添加基本情况)

// ground case
void foo ()
{ }

// recursion case
template <typename T, typename ... Ts>
void foo (T const & value, Ts const & ... args)
{
bar(value);
foo(args...);
}

下面是一个完整的工作示例

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>{}> bar (T const & value)
{ std::cout << "integral case: " << value << std::endl; }

template <typename T>
std::enable_if_t<std::is_floating_point<T>{}> bar (T const & value)
{ std::cout << "floating case: " << value << std::endl; }

// ground case
void foo ()
{ }

// recursion case
template <typename T, typename ... Ts>
void foo (T const & value, Ts const & ... args)
{
bar(value);
foo(args...);
}

int main ()
{
float f {5.5};
int i {2};

foo(f, i, i, 3L, 6.6f);
}

-- 编辑 --

OP 说

The main problem is still left unsolved - bars have to be defined before foo.

如果您接受 bar 成为结构中的静态方法,我建议使用以下 bar 结构

struct bar
{
template <typename T>
static std::enable_if_t<std::is_integral<T>{}> func (T const & value)
{ std::cout << "integral case: " << value << std::endl; }

template <typename T>
static std::enable_if_t<std::is_floating_point<T>{}> func (T const & value)
{ std::cout << "floating case: " << value << std::endl; }
};

foo成为

//地面情况

template <typename>
void foo ()
{ }

// recursion case
template <typename Bar, typename T, typename ... Ts>
void foo (T const & value, Ts const & ... args)
{
Bar::func(value);
foo<Bar>(args...);
}

调用如下

foo<bar>(f, i, i, 3L, 6.6f);

以下是一个完整的工作示例,其中 bar 结构在 foo() 之后定义

#include <iostream>
#include <type_traits>

// ground case
template <typename>
void foo ()
{ }

// recursion case
template <typename Bar, typename T, typename ... Ts>
void foo (T const & value, Ts const & ... args)
{
Bar::func(value);
foo<Bar>(args...);
}

struct bar
{
template <typename T>
static std::enable_if_t<std::is_integral<T>{}> func (T const & value)
{ std::cout << "integral case: " << value << std::endl; }

template <typename T>
static std::enable_if_t<std::is_floating_point<T>{}> func (T const & value)
{ std::cout << "floating case: " << value << std::endl; }
};

int main ()
{
float f {5.5};
int i {2};

foo<bar>(f, i, i, 3L, 6.6f);
}

关于c++ - 顺序独立的可变参数模板基础特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47160148/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com