My template needs two types, one that I expect the caller to explicitly specify, the other which should be deducible by the compiler. Yet it requires me to specify it. Commenting out the foo2 line results in a clean build. Is there a way to get the foo2-type variable construction to work?
(The toy example program counts, in a variable of any math type, the number of allocations it makes for you of memory for the explicitly-supplied type.)
#include <cstdlib>
template<class T, class U> class Foo {
public:
Foo( U* counter_in ) : counter( counter_in ) {};
U* counter;
T* Alloc() { *counter += 1; return (T*) malloc( sizeof(T) ); };
};
int iCounter = 0;
Foo<double, int> foo1( &iCounter );
Foo<double> foo2( &iCounter );
int main( int nArg, const char* apszArg[] ) {
double* pd = foo1.Alloc();
return 0;
}
Compiler output:
> g++ -std=c++23 -c -o t.o t.cpp
t.cpp:12:11: error: wrong number of template arguments (1, should be 2)
12 | Foo<double> foo2( &iCounter );
| ^
t.cpp:3:34: note: provided for 'template<class T, class U> class Foo'
3 | template<class T, class U> class Foo {
| ^~~
t.cpp:12:19: error: invalid conversion from 'int*' to 'int' [-fpermissive]
12 | Foo<double> foo2( &iCounter );
| ^~~~~~~~~
| |
| int*
t.cpp: In function 'int main(int, const char**)':
t.cpp:15:18: error: 'foo' was not declared in this scope; did you mean 'Foo'?
15 | double* pd = foo.Alloc();
| ^~~
| Foo
> g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/14/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,m2,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-libstdcxx-backtrace --with-libstdcxx-zoneinfo=/usr/share/zoneinfo --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-14.0.1-20240411/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none,amdgcn-amdhsa --enable-offload-defaulted --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux --with-build-config=bootstrap-lto --enable-link-serialization=1
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 14.0.1 20240411 (Red Hat 14.0.1-0) (GCC)
CTAD is a whole or nothing.
You might create a template make_Foo
:
template <typename T, typename U>
Foo <T, U> make_Foo(U* u) { return Foo<T, U>(u); }
and then
auto foo2 = make_Foo<double>( &iCounter );