我有一個類Foo,有兩個任意數據成員類型A和B.調用Foo :: operator()(Arg & &)將參數轉發給兩個成員並返回結果的總和。我可以看到幾種方法來實施所有必要的類型扣除。有沒有一些方法是首選,並減少編譯器的壓力?我的意思是編譯時意義上的「緊張」,如果嵌套得太深,就會觸及內部限制等等。你能概括一下它,還是對給定的編譯器來說是非常具體的?返回類型推理:什麼方法是首選?
我能做的「天真」自動decltype變種:
template <typename A, typename B>
class Foo
{
public:
Foo(A a, B b) : m_a(std::move(a)), m_b(std::move(b)) { }
template <typename Arg>
auto operator()(Arg && arg) -> decltype(m_a(std::forward<Arg>(arg)) + m_b(std::forward<Arg>(arg)))
{
return m_a(std::forward<Arg>(arg)) + m_b(std::forward<Arg>(arg));
}
private:
A m_a;
B m_b;
};
我可以寫,只有在類型,而不是「真實」的實例,但通過的std :: declval創建者操作的輔助結構<>
template <typename A, typename B, typename Arg>
struct Foo_Returns
{
typedef decltype(std::declval<A>()(std::declval<Arg>()) +
std::declval<B>()(std::declval<Arg>())) type;
}
template <typename A, typename B>
class Foo
{
public:
Foo(A a, B b) : m_a(std::move(a)), m_b(std::move(b)) { }
template <typename Arg>
typename Foo_Returns<A, B, Arg>::type
operator()(Arg && arg)
{
return m_a(std::forward<Arg>(arg)) + m_b(std::forward<Arg>(arg));
}
private:
A m_a;
B m_b;
};
有沒有更多的可能性?
現在讓我們更難:我們有兩個特徵is_green <>並且是_blue <>。如果Arg爲綠色,則Foo的運算符()應將Arg轉發給A和B的成員函數爲綠色,並返回結果的總和,類似於Arg爲藍色。一個類型永遠不會是綠色和藍色。應該可以添加更多的類型(所以使用bool值來表示不允許藍色或綠色)。
一個變種會使用標籤調度和經銷商 - > decltype(...)儘可能:
struct green_tag { };
struct blue_tag { };
struct error_tag;
template <typename T>
struct category
{
typedef typename std::conditional<is_green<T>::value,
green_tag,
typename std::conditional<is_blue<T>::value,
blue_tag,
error_tag
>::type
>::type type;
}
template <typename A, typename B>
class Foo
{
public:
Foo(A a, B b) : m_a(std::move(a)), m_b(std::move(b)) { }
template <typename Arg>
auto operator()(Arg && arg) -> decltype(impl(std::forward<Arg>(arg), typename category<Arg>::type()))
{
return impl(std::forward<Arg>(arg), typename category<Arg>::type());
}
private:
template <typename Arg>
auto impl(Arg && arg, green_tag) -> decltype(m_a.green(std::forward<Arg>(arg)) + m_b.green(std::forward<Arg>(arg)))
{
return m_a.green(std::forward<Arg>(arg)) + m_b.green(std::forward<Arg>(arg));
}
template <typename Arg>
auto impl(Arg && arg, blue_tag) -> decltype(m_a.blue(std::forward<Arg>(arg)) + m_b.blue(std::forward<Arg>(arg)))
{
return m_a.blue(std::forward<Arg>(arg)) + m_b.blue(std::forward<Arg>(arg));
}
A m_a;
B m_b;
};
另一個版本可以使用的輔助結構:
template <typename A, typename B, typename Arg, typename Category = typename category<Arg>::type>
struct Foo_Returns;
template <typename A, typename B, typename Arg>
struct Foo_Returns<A, B, Arg, green_tag>
{
typedef decltype(std::declval<A>().green(std::declval<Arg>()) +
std::declval<B>().green(std::declval<Arg>())) type;
type operator()(A & a, B & b, Arg && arg) const
{
return a.green(std::forward<Arg>(arg)) + b.green(std::forward<Arg>(arg));
}
};
template <typename A, typename B, typename Arg>
struct Foo_Returns<A, B, Arg, blue_tag>
{
typedef decltype(std::declval<A>().blue(std::declval<Arg>()) +
std::declval<B>().blue(std::declval<Arg>())) type;
type operator()(A & a, B & b, Arg && arg) const
{
return a.blue(std::forward<Arg>(arg)) + b.blue(std::forward<Arg>(arg));
}
};
template <typename A, typename B>
class Foo
{
public:
Foo(A a, B b) : m_a(std::move(a)), m_b(std::move(b)) { }
template <typename Arg>
typename Foo_Returns<A, B, Arg>::type
operator()(Arg && arg)
{
return Foo_Returns<A, B, Arg>()(m_a, m_b, std::forward<Arg>(arg));
}
private:
A m_a;
B m_b;
};
是任何版本的比較好?還有哪些其他方法可行?
gcc-4.8用'-std = C++ 1y'和'auto'作爲返回類型。 ;) – inf 2013-03-18 17:16:51
我還沒有讀你寫的所有。但是當你使用成員時,當你的成員函數是const的時候它也可以工作(成員將被視爲const)。還需要在函數之前聲明成員。就像你的代碼一樣,它不起作用。 – 2013-03-18 17:38:46