获取模板以推断出函数参数的确切类型

时间:2013-09-30 19:29:03

标签: c++ templates

我无法获取模板来推断出功能参数的确切类型。

在此示例中, callit 的调用不会推断出我想要的参数类型。 callitA 的第一次调用将推导出[int,int,int,int]。 callitB 的第二次调用将推导出[const int&,int&,const int&,int&]。只有当我对模板进行特定的实例化时才能获得正确的参数。

如何在不明确指定模板参数的情况下获得下面3中的行为。它们应该从函数参数中推导出来。

提前致谢。

void read() {}

template< typename P, typename... Args >
void read(const P & p, Args&... args) {
   // p is a constant and shall not be written to.
   read(args...);
}

template< typename P, typename... Args >
void read(P & p, Args&... args) {
   cin >> p;
   read(args...);
}

template< typename... Args >
void callitA(Args... args) {
   read( args... );
}

template< typename... Args >
void callitB(Args&... args) {
   read(args...);
}

// b is the only variable that can be returned from funk.
void funk(const int & a, int & b, const int c, int d) {
   callitA(a, b, c, d);  // 1. Args will be [int, int, int, int]
   callitB(a, b, c, d);  // 2. Args will be [const int &, int &, const int &, int &]

   // 3. Here Args will be what I want [const int &, int &, const int, int]
   callitA<const int &, int &, const int, int>(a, b, c, d);
}

void main() {
   const int a = 1;
   int b = 0;
   const int c = 3;
   int d = 4;

   funk(a, b, c, d);

   cout << b << endl;
}

2 个答案:

答案 0 :(得分:0)

在您的函数func()中,所有四个参数都是左值,并且cd是参数无法区分。如果您在c查看时将dcallitA()设为rvalues,则需要std::move()

以下是一个在推断传递的参数方面做得更好的程序:

#include <iostream>

void read() {
    std::cout << '\n';
}

template <typename T>
struct type_to_string;
template <>
struct type_to_string<int&> {
    static constexpr char const* value = "int&";
};
template <>
struct type_to_string<int const&> {
    static constexpr char const* value = "int const&";
};
template <>
struct type_to_string<int> {
    static constexpr char const* value = "int";
};

template <>
struct type_to_string<int const> {
    static constexpr char const* value = "int const";
};

template< typename P, typename... Args >
void read(P&&, Args&&... args) {
    std::cout << type_to_string<P>::value << ", ";
    read(std::forward<Args>(args)...);
}

template< typename... Args >
void callitA(Args... args) {
   read( args... );
}

template< typename... Args >
void callitB(Args&... args) {
   read(args...);
}

template< typename... Args >
void callitC(Args&&... args) {
    read(std::forward<Args>(args)...);
}

void funk(const int & a, int & b, const int c, int d) {
   callitA(a, b, c, d);
   callitB(a, b, c, d);
   callitC(a, b, std::move(c), std::move(d));
}

int main() {
   const int a = 1;
   int b = 0;
   const int c = 3;
   int d = 4;

   funk(a, b, c, d);
   callitC(a, b, static_cast<int const>(3), 4);
}

答案 1 :(得分:0)

感谢所有答案。那里有很多有趣的东西 不幸的是,这是我似乎能够做我想做的唯一方式。

以下程序产生以下输出:
int const,int,int const,int const,
int const,int,int const,int const,

重要的是只有第二个参数'b'是非const的,所以我可以重载读取函数只读取这个参数。

void read() {
   std::cout << '\n';
}

template <typename T>
struct type_to_string;
template <>
struct type_to_string<int&> {
   static char const* value;
};
char const* type_to_string<int&>::value = "int&";
template <>
struct type_to_string<int const&> {
   static char const* value;
};
char const* type_to_string<int const&>::value = "int const&";
template <>
struct type_to_string<int> {
   static char const* value;
};
char const* type_to_string<int>::value = "int";

template <>
struct type_to_string<int const> {
   static char const* value;
};
char const* type_to_string<int const>::value = "int const";

template< typename P, typename... Args >
void read(P&, Args&... args) {
   cout << type_to_string<P>::value << ", ";
   read( args...);
}

template< typename... Args >
void callitC(Args&... args) {
   read( args...);
}

// b is the only variable that can be returned from funk.
void funkA(const int & a, int & b, const int c, int d) {
   callitC(a, b, c, const_cast<const int &>(d));
}

// b is the only variable that can be returned from funk.
void funkB(const int & a, int & b, const int c, int d) {
   callitC<const int &, int &, const int, const int>(a, b, c, d);
}

void main() {
   const int a = 1;
   int b = 0;
   const int c = 3;
   int d = 4;

   funk(a, b, c, d);
   cout << endl;
   funkB(a, b, c, d);
}