Template template parameter and default values [duplicate]
Asked Answered
R

1

11

Consider the following code:

template<typename T>
struct A { };

// same as A, but with one extra defaulted parameter
template<typename T, typename F = int>
struct B { };

template<template<typename> typename T>
T<int> build() { return {}; }

int main()
{
    build<A>();  // works in gcc and clang
    build<B>();  // works in gcc, does not work in clang
}

g++ (7.3.0) compiles the code just fine, however, clang++ (5.0.1) emits the following:

example.cpp:14:5: error: no matching function for call to 'build'
    build<B>();  // works in gcc, does not work in clang
    ^~~~~~~~
example.cpp:9:8: note: candidate template ignored: invalid
      explicitly-specified argument for template parameter 'T'
T<int> build() { return {}; }

Which of the compilers is right?


Note: The important line is obviously:

template<template<typename> typename T>

Because both compilers are satisfied with:

template<template<typename...> typename T>

So the question is whether default values should be considered when passing template template arguments.

Ruprecht answered 6/2, 2018 at 14:23 Comment(7)
Fail on c++14, succeed with C++17 with gcc: Demo.Streptokinase
A far I know, your code is correct starting from C++17 thanks to P0522, wrong before.Aplanospore
@Aplanospore Thank you. Can you make it a full answer? It just seems that clang has not implemented P0522 yet.Ruprecht
I copy/pasted the sample code to Wandbox and tried to compile with clang HEAD 7.0.0 and C++2a. The output is similar to that in the question. Life demoCirilla
@Ruprecht - done; with a little improvement.Aplanospore
Maybe a duplicate of this question, or this question.Eoin
... or this one or this one or this oneGaussmeter
A
7

As far I know, your code is correct starting from C++17, wrong before.

This according P0522R0, that is part of new standard, where I see an example that is very, very similar to your code (see "overview"):

template <template <typename> class> void FD();
template <typename, typename = int> struct SD { /* ... */ };
FD<SD>();  // OK; error before this paper (CWG 150)

According the compiler support tables in ccpreference, g++ support P0522R0 from version 7, clang++ from version 4. So both compiler should support your code.

But looking the table in this page, the support for llvm (clang) 5 is defined "partial" and, according a note,

(12): Despite being the the resolution to a Defect Report, this feature is disabled by default in all language versions, and can be enabled explicitly with the flag -frelaxed-template-template-args in Clang 4 onwards. The change to the standard lacks a corresponding change for template partial ordering, resulting in ambiguity errors for reasonable and previously-valid code. This issue is expected to be rectified soon.

So, at your risk, you can try with the flag -frelaxed-template-template-args.

Aplanospore answered 6/2, 2018 at 16:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.