繁体   English   中英

对可变参数模板函数的模棱两可的调用

[英]Ambiguous call to variadic template function

我正在创建一些类,这些类以数学含义表示函数,并且它们的界面要“数学友好”。 为此,我想创建一个可变参数模板operator()方法,该方法允许用户以这种方式编写定义函数f(x, y) = 2*x + y; 然后通过调用f(4, 5);获取其值f(4, 5); 我无法预测参数的数量(数学函数中变量的数量),因此我决定使用可变参数模板。 但是,两次重载operator()作为可变参数模板并调用它会导致“歧义调用”错误。 有什么方法可以克服它,还是我必须创建两个单独的方法?

//expressions like f(x, y, z) = x*x+y-z    
template <typename... Args>
RichFunction<T> &operator()(Args&&... args)
{
        mMainLinears.clear();
        setMainLinears(args...);
        return *this;
}

//expressions like f(5, 4, 3)
template <typename... Args>
T operator()(Args&&... args)
{
    Function<T>::assign(mMainLinears, 0, args...);
    return Function<T>::value();
}

编辑:整个背景不是很重要。 我只需要知道如何重载可变参数模板方法,重载的版本仅在参数类型上有所不同。

根据您的描述,我想您比可变参数模板更需要lambda表达式 例如:

auto f = [](double x, double y) { return 2 * x + y; };
std::cout << f(4, 5) << '\n';

如果SFINAE不能满足您的任何先决条件,则可以SFINAE之一。

如果我对您的理解正确,则第一个operator()应该定义您的数学表达式,而第二个运算符应该对之前定义的该表达式求值。

要回答您的问题:您不能以这种方式重载方法operator(),因为这两个方法中的签名是相同的,即模板定义和参数列表完全相同。 编译器应如何知道要调用的方法? 必须有一种方法来区分这两个呼叫。

建议(1)解决方案

可能变量(x,y,z)是某种类型的。 您可以使用CRTP模式定义一个通用基类

template <class Sub>
struct Variable {};

struct X : Variable<X> {};
struct Y : Variable<Y> {}; //...

然后,您可以基于以下类结构进行重载:

template <class... Xs>
ReturnType operator()(Variable<Xs>&&... vars) {...}

在此方法内部,您可以static_cast<X&>(var)转换为具体的变量类型,例如,通过对static_cast<X&>(var) Variable<X>& var类型的具体参数使用static_cast<X&>(var)

建议(2)

使用enable_ifdisable_if (来自boost或std)来区分传递给方法的两种参数类型,即

template <class... Ts>
typename enable_if< is_scalar<Ts...>, ReturnType>::type 
operator()(Ts&&... values) { ... }

template <class... Ts>
typename disable_if< is_scalar<Ts...>, ReturnType>::type 
operator()(Ts&&... vars) { ... }

在所有类型均为标量(数字)的情况下,其中is_scalar必须是可以接受可变参数模板并定义静态布尔成员值的任何元方法。

据我所知,仍然没有办法通过返回值来消除歧义(尽管您可以通过模板参数来消除歧义)。 如果您想要保留语法,则可能想将用于创建函数的方法放在与调用该函数的对象不同的对象中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM