Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 具有多模板继承的模板实例化_C++_Templates_Language Lawyer_Overload Resolution - Fatal编程技术网

C++ 具有多模板继承的模板实例化

C++ 具有多模板继承的模板实例化,c++,templates,language-lawyer,overload-resolution,C++,Templates,Language Lawyer,Overload Resolution,当我们将(多)派生类传递给需要基类的模板函数时,模板实例化的规则是什么?例如: #include <iostream> template <int x> struct C {}; struct D : C<0>, C<1> {}; template <int x> void f (const C<x> &y) { std::cout << x << "\n"; } int main

当我们将(多)派生类传递给需要基类的模板函数时,模板实例化的规则是什么?例如:

#include <iostream>

template <int x>
struct C {};

struct D : C<0>, C<1> {};

template <int x>
void f (const C<x> &y)  { std::cout << x << "\n"; }

int main ()
{
  f (D ());
}
#包括
模板
结构C{};
结构D:C,C{};
模板
void f(const C&y){std::coutgcc 5.4:

/tmp/gcc-explorer-compiler11685-58-1h67lnf/example.cpp: In function 'int main()':
13 : error: no matching function for call to 'f(D)'
f (D ());
^
9 : note: candidate: template<int x> void f(const C<x>&)
void f (const C<x> &y) { std::cout << x << "\n"; }
^
9 : note: template argument deduction/substitution failed:
13 : note: 'const C<x>' is an ambiguous base class of 'D'
f (D ());
^
Compilation failed

在我看来,它们似乎都错了。这不是一个模棱两可的函数调用吗?“MSVC打印0,clang-1,gcc给出编译器错误。”,哪个MSVC,哪个gcc,哪个clang?@PiotrSkotnicki添加了版本号,但它们的行为都是相同的。4.0拒绝了这两个示例(尽管3.8编译了它们)。C++从不优先选择第一个(或最后一个或任何其他)基,因此任意选取基的任何编译器都是错误的。对基进行重新排序应该不会对程序的有效性产生任何影响(可能存在一些不正确的情况,但这肯定不是其中之一;我无法立即想出任何错误).在第一个示例中-是的,我认为应该是不明确的,在第二个示例中-否,应该只启用C的重载。“应该只启用C的重载”您为什么认为编译器应该尝试使用每个可能的
x
fails@PiotrSkotnicki我问这个问题是为了了解应该如何做。如果你手动编写这个函数,那么它将按预期工作:@AlexTelishev这个要点中没有任何推论,只有重载re解决方案和SFINAE.substitution失败可能发生在推断的基础上;在这种情况下,编译器会退回到其他重载,而不是相同的其他可能实例化template@PiotrSkotnicki是的,我想说的是,在没有扣除的情况下,它是有效的。有没有办法强制所有基类使用它?
/tmp/gcc-explorer-compiler11685-58-1h67lnf/example.cpp: In function 'int main()':
13 : error: no matching function for call to 'f(D)'
f (D ());
^
9 : note: candidate: template<int x> void f(const C<x>&)
void f (const C<x> &y) { std::cout << x << "\n"; }
^
9 : note: template argument deduction/substitution failed:
13 : note: 'const C<x>' is an ambiguous base class of 'D'
f (D ());
^
Compilation failed
#include <utility>
#include <iostream>

template<class T>
struct has_type
{
    template<class U> static auto test(U*) -> decltype(typename U::type{}, std::true_type());
    static auto test(...) -> decltype(std::false_type());
    using type = decltype(test((T*)0));
    static const auto value = type::value;
};

template <int x> struct C {};

template<>
struct C<0> { using type = int; };

template<int...xs>
struct enumerates_C : C<xs>...
{
};

struct D : enumerates_C<0, 1> {};

template<int x, std::enable_if_t<has_type<C<x>>::value>* = nullptr>
void f_impl(const C<x>& y)
{
    std::cout << x << "\n";
}

template<int x, std::enable_if_t<not has_type<C<x>>::value>* = nullptr>
void f_impl(const C<x>& y)
{
    // do nothing
}

template <int...xs>
void f (const enumerates_C<xs...> &y)
{
    using expand = int[];
    void(expand { 0,
        (f_impl(static_cast<C<xs> const &>(y)),0)...
    });
}

int main ()
{
    f (D ());
}
0