我需要一种特殊的可变容器并且有一些不可预知的问题,所以我创建了以下最小的例子(见注释):
#include <iostream>
#include <tuple>
//---------------------------------------------------
template<class...Ts>
class container
{
using ts_type = std::tuple<Ts...>;
public:
container() = default;
container(Ts... ts) : ts_{std::move(ts)...} {}
// get #1: member template
template<std::size_t index>
auto
get() const -> decltype(std::get<index>(std::declval<const ts_type>())) {
return std::get<index>(ts_);
}
// get #2: friend function
template<std::size_t index>
friend typename std::tuple_element<index,ts_type>::type
get(const container& c) {
return std::get<index>(c.ts_);
}
// get #3: friend function with type deduction
// won't compile
// error: 'const class container<int, double>' has no member named 'ts_'
//
// template<std::size_t index>
// friend auto
// get(const container& c) -> decltype(std::get<index>(c.ts_)) {
// return std::get<index>(c.ts_);
// }
private:
ts_type ts_;
};
//---------------------------------------------------
// WTF? g++ already complains about the declaration
// I'm not even trying to instantiate foo
template<class T>
void foo(const T& t) {
// error: expected primary-expression before ')' token
std::cout << t.get<0>() << std::endl;
// error: 'get' was not declared in this scope
std::cout << get<0>(t) << std::endl;
}
//---------------------------------------------------
int main() {
// this compiles and runs just fine ... as expected
auto c = container<int,double>{1, 2.5};
std::cout << c.get<0>() << std::endl;
std::cout << c.get<1>() << std::endl;
std::cout << get<0>(c) << std::endl;
std::cout << get<1>(c) << std::endl;
}
这里发生了什么?为什么g ++(4.7.2)会抱怨foo中的声明?为什么container :: get#3不能编译?
我想像get&lt; 0&gt;这样的东西只能在具体类型上调用?
这种行为符合标准吗?
答案 0 :(得分:0)
您有一个可修复的问题和一个不可解决的问题:
在foo
中,您需要告诉编译器您正在调用模板:
std::cout << t.template get<0>() << std::endl;
同样在foo
中,独立函数get
取决于容器的实例化,这在使用时是不可用的(您可能之前明确地实例化容器,但我认为没有修复)。
另一个问题是评论代码(#3)。在这里,我将ts_type ts_
作为公共成员放在get(const container& c) -> decltype(std::get<index>(c.ts_))
前面,但这并没有回答这个问题。
答案 1 :(得分:0)
好的,现在可以了!谢谢你的帮助!
#include <iostream>
#include <tuple>
//---------------------------------------------------
template<class...Ts>
class container
{
using ts_type = std::tuple<Ts...>;
public:
container() = default;
container(Ts... ts) : ts_{std::move(ts)...} {}
template<std::size_t index>
auto
get() const -> decltype(std::get<index>(std::declval<const ts_type>())) {
return std::get<index>(ts_);
}
template<std::size_t index, class... Us>
friend auto
get(const container<Us...>& c) -> decltype(std::get<index>(c.ts_));
private:
ts_type ts_;
};
template<std::size_t index, class... Us>
auto get(const container<Us...>& c) -> decltype(std::get<index>(c.ts_)) {
return std::get<index>(c.ts_);
}
//---------------------------------------------------
template<class T>
void foo(const T& t) {
std::cout << t.template get<0>() << std::endl;
std::cout << get<0>(t) << std::endl;
}
//---------------------------------------------------
int main() {
auto c = container<int,double>{1, 2.5};
std::cout << c.get<0>() << std::endl;
std::cout << c.get<1>() << std::endl;
std::cout << get<0>(c) << std::endl;
std::cout << get<1>(c) << std::endl;
foo(c);
}