Tôi muốn hỏi xem mã sau có hợp lệ không.Nhiều mở rộng của nhiều gói thông số trong cùng một biểu thức
Tôi tự hỏi về khả năng mở rộng gói tham số nhiều lần trong một biểu thức.
#include <iostream>
#include <tuple>
class ExpandWithConstructor
{
public:
template <typename ... T>
ExpandWithConstructor(T... args) { }
};
template <typename T>
int PrintArgs(T arg)
{
std::cout << arg << ", ";
return 0;
}
template <typename Head, typename ... T>
class DebugPrinter: public DebugPrinter<T...>
{
public:
DebugPrinter() { }
template< typename ...Y>
DebugPrinter(Y ... rest)
{
std::cout << "Construction of: " << __PRETTY_FUNCTION__ << " Values: " ;
ExpandWithConstructor{PrintArgs(rest)...};
std::cout << std::endl;
}
};
template <typename Head>
class DebugPrinter<Head>
{
public:
};
template <typename ... T>
class TypeContainer: public std::tuple<T...>
{
public:
TypeContainer(T... args):std::tuple<T...>(args...){};
};
template <typename... T1> class CheckVariadic;
template <typename... T1, typename ...T2>
class CheckVariadic< TypeContainer<T1...>, TypeContainer<T2...>> :
public DebugPrinter< T1, T2, T1...>...
{
public:
CheckVariadic(T1... args1, T2... args2, T1... args3): DebugPrinter< T1, T2, T1...>(args1, args2..., args1)... {}
};
int main()
{
CheckVariadic< TypeContainer<int,float>, TypeContainer<char, void*>> checkVariadic1{ 1,2.2,'c',(void*)0xddddd,5,6.6,};
}
Như bạn có thể thấy mã sử dụng: DebugPrinter < T1, T2, T1 ...> ...
nếu T1 được đưa ra với "int, float" và T2 là "char, void *" mà mở rộng để
DebugPrinter< T1, T2, int, float>...
mà mở rộng để
DebugPrinter< int, char, int, float>
DebugPrinter< float, void*, int, float>
Việc mở rộng cùng đi với:
DebugPrinter< T1, T2, T1...>(args1, args2..., args1)...
mã biên dịch với clang3.3 nhưng KHÔNG với gcc4.8.1 vì vậy tôi muốn hỏi nếu mã là hợp lệ hay không.
Cập nhật: gcc 7.2 vẫn chưa biên dịch mã.
tôi có thể làm cho nó biên dịch trong g ++ 4.7 bằng cách sử dụng 'DebugPrinter {args1, args2 ..., args1} ... ', nhưng đầu ra ở hướng ngược lại của tiếng kêu. –
kennytm
Thứ tự đảo ngược của các cuộc gọi hàm từ một danh sách khởi tạo hàm dựng là một lỗi đã biết trong g ++. Tôi cũng có thể biên dịch mã bằng g ++ 4.7.2. Nhưng g ++ 4.8.1 vẫn không thành công. – Klaus
@KennyTM: chính xác, đối với các hàm thông thường, thứ tự đánh giá của các đối số không được chỉ định; lịch sử g ++ đã sử dụng thứ tự từ phải sang trái. Đối với một danh sách initializer tôi tin rằng thứ tự được chỉ định và g + + chỉ đơn giản là không nhận được để cập nhật nó được nêu ra. –