是否可以“传递”未命名的参数而不创建临时变量?

时间:2016-03-23 23:47:36

标签: c++

我正在使用未命名参数编写一个基于类型的简单调度程序,这是一个非常正常的事情。

当实际调用该函数时,我想在没有任何变量的情况下获取重载。有可能吗?

E.g。

void f1(int /*can change the type*/) {
}
int main(int, char*) {
  f1(/*what to put here?*/); 
  return 0;
}

我的“真实”示例是一个简单的基于类型的调度程序。我提出的最好的是一个指针作为未命名的参数,我认为它可能有最小的开销:

#include <iostream>
using namespace std;

template<typename U>
class A {
public:

A(const U& u) : u(u) {};

template <typename T>
T get_as() {
    T* t; // <- ugly
    return get(t);
}

U get(U*) {
    return u;   
}

int get(int*) {
    return i;
}

double get(double*) {
    return d;
}

private:
    U u;
    int i = 5;
    double d = 3.14;
};

int main() {
    A<string> a("name");
    cout << a.get_as<double>() << '\n';
    cout << a.get_as<int>() << '\n';
    cout << a.get_as<string>() << '\n';
    return 0;
}

我猜这是一个纯粹的美学与指针,因为它可能已经优化,但我仍然想知道。我也猜测这可能是不可能的,因为(AFAIK)这个论点经历了堆栈。所以在技术上总有这种“开销”。这是对的吗?

不确定这是否应该是另一个问题,但是有没有办法表达,“只是拿出这个过载”而没有诡计?

PS。我发现我可以在“丑陋”的行中使用T*(0),但它的可读性可能更低。

2 个答案:

答案 0 :(得分:6)

您无法获得比传递空标记结构更清晰或更高效的信息:

template<class T> struct tag {};

double get(tag<double>) {
    return d;
}

template <typename T>
T get_as() {
    return get(tag<T>{});
}

使用指针类型进行调度的一个优点是没有意外间接传入空指针的危险。

(旁边:What happens to empty classes in the AMD64 ABI? - 但您的来电通常会被内联。)

答案 1 :(得分:1)

既然你在谈论“美学”,我想知道这是否对你有帮助:

Live Demo

template<typename U>
class A
{
public:
    static_assert(!std::is_same<int, U>::value && !std::is_same<double,U>::value,
                               "Template argument cannot be <int> or <double>.");
    A(const U& u) : u(u) {};
    explicit operator U() { return u; }
    explicit operator int() { return i; }
    explicit operator double() { return d; }

private:
    U u;
    int i = 5;
    double d = 3.14;
};

int main()
{
    A<string> a("wow");
    cout << double(a) << '\n';
    cout << int(a) << '\n';
    cout << string(a) << '\n';
    return 0;
}

我认为用户定义的转换运算符如果是显式的,则不是邪恶的。

你不能用“错误”来使用它们。此外,这个类应该没有开销。