简体   繁体   English

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

[英]Ambiguous call to variadic template function

I'm creating some classes which represent the functions in the mathematical meaning and their interface is to be 'math-friendly'. 我正在创建一些类,这些类以数学含义表示函数,并且它们的界面要“数学友好”。 To accomplish this I want to create a variadic template operator() methods, which allow user to write defining functions in this way f(x, y) = 2*x + y; 为此,我想创建一个可变参数模板operator()方法,该方法允许用户以这种方式编写定义函数f(x, y) = 2*x + y; and then getting its value by calling f(4, 5); 然后通过调用f(4, 5);获取其值f(4, 5); . I cannot predict the number of parameters (the number of variables in mathematical function) so I decided to use variadic templates. 我无法预测参数的数量(数学函数中变量的数量),因此我决定使用可变参数模板。 However overloading operator() twice as a variadic template and calling it causes the "ambigous call" error. 但是,两次重载operator()作为可变参数模板并调用它会导致“歧义调用”错误。 Is there some way to overcome it, or do I have to create two seprate methods? 有什么方法可以克服它,还是我必须创建两个单独的方法?

//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();
}

Edit: The whole background isn't very important. 编辑:整个背景不是很重要。 I only need to know how to overload variadic template method, where overloaded versions differ from each other only with arguments type. 我只需要知道如何重载可变参数模板方法,重载的版本仅在参数类型上有所不同。

Based on your description, I guess you need lambda expression more than variadic templates. 根据您的描述,我想您比可变参数模板更需要lambda表达式 For illustration: 例如:

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

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

If I understand you correctly, the first operator() should define your mathematical expression and the second one should evaluate this expression defined previously. 如果我对您的理解正确,则第一个operator()应该定义您的数学表达式,而第二个运算符应该对之前定义的该表达式求值。

To answer your question: you can not overload the method operator() in this way, since the signature in both methods is the same, ie exactly the same template definition and argumentlist. 要回答您的问题:您不能以这种方式重载方法operator(),因为这两个方法中的签名是相同的,即模板定义和参数列表完全相同。 How should the compiler know which method to call? 编译器应如何知道要调用的方法? There must be a way to distinguish both calls. 必须有一种方法来区分这两个呼叫。

Suggestions (1) for a solution 建议(1)解决方案

Probably you variable (x,y,z) are of some type. 可能变量(x,y,z)是某种类型的。 You could use the CRTP-pattern to define a common base class 您可以使用CRTP模式定义一个通用基类

template <class Sub>
struct Variable {};

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

And then you could do an overload based on this class structure: 然后,您可以基于以下类结构进行重载:

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

Inside of this method you can cast to the concrete variable type, eg by using static_cast<X&>(var) for a concrete argument of type Variable<X>& var . 在此方法内部,您可以static_cast<X&>(var)转换为具体的变量类型,例如,通过对static_cast<X&>(var) Variable<X>& var类型的具体参数使用static_cast<X&>(var)

Suggestion (2) 建议(2)

Use enable_if and disable_if (from boost, or std) to distinguish between the two argument types passed to the method, ie 使用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) { ... }

where is_scalar must be any meta-method that accepts variadic templates and defines a static boolean member value in the case that all types are scalars (number). 在所有类型均为标量(数字)的情况下,其中is_scalar必须是可以接受可变参数模板并定义静态布尔成员值的任何元方法。

To the best of my knowledge, there is still no way to disambiguate methods by return value (you can disambiguate by template parameters though). 据我所知,仍然没有办法通过返回值来消除歧义(尽管您可以通过模板参数来消除歧义)。 You might wanna put the method to create a function into a separate object from the one that calls it if you want to keep the syntax. 如果您想要保留语法,则可能想将用于创建函数的方法放在与调用该函数的对象不同的对象中。

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

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